QT使用QListWidget+QChececkBox实现多选功能

功能需求描述:要求制作一个自定义控件CheckBoxList,控件中有N个复选框QCheckBox,当任何一个复选框反转时,该控件发出信号,信号指示出:此时哪几个复选框处于选中状态。

解决方案:显示出一列复选框,用QListWidget来干最合适了,默认情况下QListWidget添加的条目item是纯文字,而这里我们要求添加的条目是复选框。

同理,也可以使用树形控件QTreeWidget、表格控件QTableWidget来组织自定义控件。本文仅以列表形组织为例了:

 

UI设计界面、把它应用在别的程序中的运行效果,分别如下所示:
                
           

为了使这个自定义控件更加好用,还添加了全选、全不选、正则筛选等功能,这些功能都没什么难度。最关键的部分是要搞懂如何在QListWidget里面添加QCheckBox。

其实也简单,在ui中拖出一个或者用代码new一个QListWidget,然后在窗口的构造函数中对QListWidget添加条目即可:
 

for(int i = 0; i < cnt; i++)
    {
        QListWidgetItem *item = new QListWidgetItem();
        QCheckBox *checkBox= new QCheckBox ();

        ui->listWidget->addItem(item);//在ListWidget中添加一个条目
        ui->listWidget->setItemWidget(item, checkBox);//在这个条目中放置CheckBox
        icheckBox->setText(QString("checkBox_%1").arg(i));
        
        //把所有checkBox的信号都引向同一个槽
        connect(checkBox, SIGNAL(stateChanged(int)), this, SLOT(anyStateChanged()));
    }

/*任何一个checkBox被点击时,共同的槽函数*/
void XXXXX::anyStateChanged()
{
    //qDebug() << "one checkBox State Changed";
    selectedItems.clear();
    //遍历所有的CheckBox,把所有选中的CheckBox索引号都记录到QStringList selectedItems中
    for(int i = 0; i < ui->listWidget->count(); i++)
    {        
        QListWidgetItem *item = ui->listWidget->item(idx);//先获取QListWidgetItem
        QCheckBox *checkBox = static_cast<QCheckBox *>(ui->listWidget->itemWidget(item));//找到第i个Item对应的CheckBox
        if(checkBox->isChecked())
            selectedItems.append(i);
    }    
}

需要注意的是,任何一个CheckBox被点击都会触发anyStateChanged()这个槽函数,进行遍历所有CheckBox,如果用户点击了全选,那岂不是在一瞬间要遍历N多遍,这样做太低效,我的做法是,点击全选或者全不选时,用disConnect解除Click信号与anyStateChanged()槽的connect,然后自己构建编号的List并emit出去,然后再重新connect他们。

注意上面的ui->listWidget->setItemWidget(item, checkBox),其实我们不仅能向QLishWidget里面放置CheckBox,任何QWidget都可以放,我们可以自定义一个QWidget,里面包含好几个基本控件,然后把这个含有多个基本控件的自定义的Widget一并放到QLishWidget的每一个item里去。

我的一个项目的应用场景中,不仅要支持多选,还要实时显示每一项的数值,效果如下:


代码已上传到CSDN,下载链接见评论
 

 

-----------------------2020.10.15后记---------------------------

突然发现一个QButtonGroup类,用这个类可以大幅简化上述工作,这个组只是一个逻辑组,不会在界面上产生效果。

大体思路就是,把任意按钮(包括普通按钮、单选按钮、复选按钮等都可以)加入这个组,然后组内任何一个按钮被点击时,QButtonGroup会有信号指示出,是组内哪个按钮发生了动作。

 

可以使用 `QStackedWidget` 和 `QListWidget` 实现界面切换功能。 1. 首先,在 Qt Designer 中创建一个 `QStackedWidget` 和一个 `QListWidget`,将 `QListWidget` 放置在需要显示菜单的位置上,将 `QStackedWidget` 放置在需要显示页面的位置上。 2. 在 `QListWidget` 中添加菜单项,并设置相应的文本和图标。 3. 在 `QStackedWidget` 中添加页面,并设置相应的 UI 界面。 4. 编写槽函数,用于响应 `QListWidget` 中菜单项的点击事件,并切换到相应的页面。 以下是示例代码: ```python from PyQt5.QtWidgets import QApplication, QMainWindow, QListWidget, QStackedWidget, QWidget, QVBoxLayout, QLabel, QPushButton class MainWindow(QMainWindow): def __init__(self): super().__init__() # 创建 QListWidget 和 QStackedWidget self.list_widget = QListWidget() self.stack_widget = QStackedWidget() # 添加菜单项 self.list_widget.addItem("Page 1") self.list_widget.addItem("Page 2") self.list_widget.addItem("Page 3") # 添加页面 page1 = QWidget() layout1 = QVBoxLayout() label1 = QLabel("This is Page 1") button1 = QPushButton("Go to Page 2") button1.clicked.connect(lambda: self.stack_widget.setCurrentIndex(1)) layout1.addWidget(label1) layout1.addWidget(button1) page1.setLayout(layout1) self.stack_widget.addWidget(page1) page2 = QWidget() layout2 = QVBoxLayout() label2 = QLabel("This is Page 2") button2 = QPushButton("Go to Page 3") button2.clicked.connect(lambda: self.stack_widget.setCurrentIndex(2)) layout2.addWidget(label2) layout2.addWidget(button2) page2.setLayout(layout2) self.stack_widget.addWidget(page2) page3 = QWidget() layout3 = QVBoxLayout() label3 = QLabel("This is Page 3") button3 = QPushButton("Go to Page 1") button3.clicked.connect(lambda: self.stack_widget.setCurrentIndex(0)) layout3.addWidget(label3) layout3.addWidget(button3) page3.setLayout(layout3) self.stack_widget.addWidget(page3) # 设置 QMainWindow 的 centralWidget central_widget = QWidget() central_layout = QHBoxLayout() central_layout.addWidget(self.list_widget) central_layout.addWidget(self.stack_widget) central_widget.setLayout(central_layout) self.setCentralWidget(central_widget) # 连接 QListWidget 和 QStackedWidget self.list_widget.currentRowChanged.connect(self.stack_widget.setCurrentIndex) if __name__ == "__main__": app = QApplication([]) window = MainWindow() window.show() app.exec_() ``` 在上述示例代码中,我们在 QMainWindow 中添加了一个 `QListWidget` 和一个 `QStackedWidget`,并且在 `QListWidget` 中添加了三个菜单项,在 `QStackedWidget` 中添加了三个页面。我们通过 `setCurrentIndex` 方法切换页面,并且连接了 `currentRowChanged` 信号,以便在 `QListWidget` 中点击菜单项时,自动切换到相应的页面。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值