QTableWidget单击选中取消

来源:互联网 发布:生命最后的读书会 知乎 编辑:程序博客网 时间:2024/06/16 16:34

QTableWidget单击选中取消事件

前言

很多情况下有这样的需求,当鼠标点击QTableWidget时,每次只能选中一行或者不选中,不允许选中多行。例如:当点击表格中时选中一行,同时打开所选中的这行的详细信息(另一个GUI控件),当点击表格之外,选中行取消高亮(取消选择),同时详细信息也消失。

说明

1、QTableWidget时,选择行时,可以使用

 setSelectionBehavior(QAbstractItemView::SelectRows);

2、QTableWidget选择多个节点时,单击节点之外是可以自动取消高亮行的,现在的问题是每次只能选择一行,QT文档说明如下:

Constant

Value

Description

QAbstractItemView::SingleSelection

1

When the user selects an item, any already-selected item becomes unselected, andthe user cannot unselect the selected item by clicking on it.

QAbstractItemView::ContiguousSelection

4

When the user selects an item in the usual way, the selection is cleared and the new item selected. However, if the user presses the Shift key while clicking on an item, all items between the current item and the clicked item are selected or unselected, depending on the state of the clicked item.

QAbstractItemView::ExtendedSelection

3

When the user selects an item in the usual way, the selection is cleared and the new item selected. However, if the user presses the Ctrl key when clicking on an item, the clicked item gets toggled and all other items are left untouched. If the user presses the Shift key while clicking on an item, all items between the current item and the clicked item are selected or unselected, depending on the state of the clicked item. Multiple items can be selected by dragging the mouse over them.

QAbstractItemView::MultiSelection

2

When the user selects an item in the usual way, the selection status of that item is toggled and the other items are left alone. Multiple items can be toggled by dragging the mouse over them.

QAbstractItemView::NoSelection

0

Items cannot be selected.

红色字体可以看出,SingleSelection模式时,再次单击选中的行,是不会取消选择的,其实,还有一个没有说明:就是单击表格之外,其实也不会取消当前的选择。

         当表格中有多行数据时,其实可以点击其他行,是可以切换的,最大的问题是,当表格只有一行数据时,如果你选中了该行后,那么无论点击哪里,该选择都取消不了,这会带来一系列的问题……

         那么如何能实现每次只选择一行,却可以在点击表格之外,可以取消当前的选择行?

 

解决方法

         通过继承,重写鼠标按下事件,在按下的时候,判断该坐标点是否在表格中,进行取消/选择高亮是可以实现的,但是,不太喜欢这样做……

         现在的方法如下,无需继承,只需要一个槽行数即可。

1、  首先我们选择使用

setSelectionBehavior(QAbstractItemView::SelectRows)设置行选择。

setSelectionMode(QAbstractItemView::ContiguousSelection);设置多行选择。

2、  使该表的信号itemSelectionChanged与某个槽关联。

3、  在槽中进行处理,使其看起来像单行选择的效果。具体说明看代码

.h文件

 

#ifndef CTESTGUI_H

#define CTESTGUI_H

 

#include <QWidget>

 

class QTableWidget;

 

class CTestGui : public QWidget

{

    Q_OBJECT

 

public:

    CTestGui(QWidget *parent =NULL);

    ~CTestGui();

 

public:

    void initLayout();

    void initTab();

    void initTabDatas();

 

public slots:

    void onItemSelectionChanged();

 

private:

    QTableWidget* m_tab;

};

 

#endif // CTESTGUI_H

 

.cpp文件

 

#include <QVBoxLayout>

#include <QTableWidget>

#include <QHeaderView>

 

#include "ctestgui.h"

 

CTestGui::CTestGui(QWidget *parent)

    : QWidget(parent)

{

    initLayout();

}

 

CTestGui::~CTestGui()

{

 

}

 

void CTestGui::initLayout()

{

    initTab();

 

    QVBoxLayout* layoyt = new QVBoxLayout(this);

    layoyt->addWidget(m_tab);

 

}

 

void CTestGui::initTab()

{

    m_tab = new QTableWidget(this);

    m_tab->setContentsMargins(0, 0, 0, 0);

    m_tab->setColumnCount(4);

 

    m_tab->horizontalHeader()->setHighlightSections(false);

    m_tab->horizontalHeader()->setStretchLastSection(true);

    m_tab->setFocusPolicy(Qt::NoFocus);

 

    m_tab->setSelectionBehavior(QAbstractItemView::SelectRows);

    m_tab->setSelectionMode(QAbstractItemView::ContiguousSelection);  //上面两句说明可以选择多行

 

    //m_tab->setEditTriggers(QAbstractItemView::NoEditTriggers);

 

    QStringList tabHeaders;

    tabHeaders << tr("Item1") << tr("Item2") << tr("Item3") << tr("Item4");

    m_tab->setHorizontalHeaderLabels(tabHeaders);//设置表头

 

    initTabDatas();

 

    connect(m_tab, &QTableWidget::itemSelectionChanged,this, &CTestGui::onItemSelectionChanged);

}

 

void CTestGui::initTabDatas()

{

    //填充数据

    int row = 0;

    m_tab->insertRow(row);//插入新行

    QTableWidgetItem *newItem1 =newQTableWidgetItem("This is A1");

    m_tab->setItem(row, 0,newItem1);

 

    QTableWidgetItem *newItem2 =newQTableWidgetItem("This is B1");

    m_tab->setItem(row, 1,newItem2);

 

    QTableWidgetItem *newItem3 =newQTableWidgetItem("This is C1");

    m_tab->setItem(row, 2,newItem3);

 

    QTableWidgetItem *newItem4 =newQTableWidgetItem("This is D1");

    m_tab->setItem(row, 3,newItem4);

 

    m_tab->insertRow(++row);//插入新行

    newItem1 = new QTableWidgetItem("This is A2");

    m_tab->setItem(row, 0,newItem1);

 

    newItem2 = new QTableWidgetItem("This is B2");

    m_tab->setItem(row, 1,newItem2);

 

    newItem3 = new QTableWidgetItem("This is C2");

    m_tab->setItem(row, 2,newItem3);

 

    newItem4 = new QTableWidgetItem("This is D2");

    m_tab->setItem(row, 3,newItem4);

 

    m_tab->insertRow(++row);//插入新行

    newItem1 = new QTableWidgetItem("This is A3");

    m_tab->setItem(row, 0,newItem1);

 

    newItem2 = new QTableWidgetItem("This is B3");

    m_tab->setItem(row, 1,newItem2);

 

    newItem3 = new QTableWidgetItem("This is C3");

    m_tab->setItem(row, 2,newItem3);

 

    newItem4 = new QTableWidgetItem("This is D3");

    m_tab->setItem(row, 3,newItem4);

 

    m_tab->insertRow(++row);//插入新行

    newItem1 = new QTableWidgetItem("This is A4");

    m_tab->setItem(row, 0,newItem1);

 

    newItem2 = new QTableWidgetItem("This is B4");

    m_tab->setItem(row, 1,newItem2);

 

    newItem3 = new QTableWidgetItem("This is C4");

    m_tab->setItem(row, 2,newItem3);

 

    newItem4 = new QTableWidgetItem("This is D4");

    m_tab->setItem(row, 3,newItem4);

 

}

 

/************************************************************************/

/*

    多选行变成单行效果的过程:

 

1、当选择的Item发生改变时,会触发itemSelectionChanged信号,进而进入到onItemSelectionChanged()函数中,

只需在该函数中控制即可

2、由于我们可能选择多行,所以我们必须先取消所有选择行,再对最后一行进行高亮(选择),取消高亮(选择)的时候,又会触发该函数,

造成递归触发,为了避免这个现象,在取消高亮的时候,先disconnect该信号与槽的连接,等取消好后,再高亮最后一行后,再恢复该信号。

注:由于每个人创建的表格的列数并不一样,所以我们只需要找到最后一个选择的item,并且高亮(选择)该item,item所在的行的其他items

也会高亮,如果再提高一点效率,我们可以判断是选择了单行(不做处理),还是选择了多行(先取消,再选择最后一行),判断是否选择单行,

只需要在选择的selectedItems()的中的条目是否是表格的列数。如果是则说明是选择单行,如果大于表格的列数,则说明是多行。

*/

/************************************************************************/

 

//SLOT

void CTestGui::onItemSelectionChanged()

{

    QList<QTableWidgetItem*>itemList =m_tab->selectedItems();

 

    if (!itemList.isEmpty())

    {

       int row;

      

       if (itemList.size() ==m_tab->columnCount()) //表明选中的是一行

       {

           //

       }

       else   //选中了多行,要进行处理,使其最终看起来是选中了一行

       {

           bool disabled = m_tab->disconnect(SIGNAL(itemSelectionChanged()));//此处一定要disconnect该信号,否则会产生递归

           if (disabled)

           {

              QTableWidgetItem*item =itemList[itemList.size() - 1];

              row = m_tab->row(item);

              m_tab->clearSelection();

              m_tab->setCurrentItem(item);

              //m_tab->setCurrentCell(row, 0);

 

              connect(m_tab, &QTableWidget::itemSelectionChanged,this, &CTestGui::onItemSelectionChanged);

           }

       }

       //do something

    }

    else

    {

       //do other something

    }

}

 

 

0 0
原创粉丝点击