功能需求描述:要求制作一个自定义控件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会有信号指示出,是组内哪个按钮发生了动作。

功能需求描述:要求制作一个自定义控件CheckBoxList,控件中有N个复选框QCheckBox,当任何一个复选框反转时,该控件发出信号,信号指示出:此时哪几个复选框处于选中状态。解决方案:显示出一列复选框,用QListWidget来干最合适了,默认情况下QListWidget添加的条目item是纯文字,而这里我们要求添加的条目是复选框。同理,也可以使用树形控件QTreeWidget、表...
使用了QListWidget,QDockWidget QListWidget类提供了一个基于项目的列表小部件 QListWidget是一个方便的类,它提供了一个列表视图,类似于QListView提供的列表视图,但是具有一个用于添加和删除项的经典基于项的接口。QListWidget使用一个内部模型来管理列表中的每个QListWidgetItem。要获得更灵活的列表视图小部件,请使用带有标准模型的QListView类。列表小部件的构造方法与其他小部件相同。QListWidget与QListView类似,都可以显示一列Item,区别在于前者可以往其中增删Item。 QListWidget确定可以同时选择列表中的多少项,以及是否可以创建复杂的项选择。这可以使用函数设置
setItemWidget(); //添加自定义控件 takeItem(row); //删除项 setSizeHint(QSize()); //设置item的高度 2.了解checkbox函数 stateChanged(int); //checkbox状态改变时发出信号 实现功能: 1.在listwidget中初始化添加复选框checkbox 2.在listwidget中在原来基础上添加复选框checkbox 3.在listwidget中 当 要用到QListWidget类的setItemWidget()函数,其原型如下: void QListWidget::setItemWidget(QListWidgetItem * item, QWidget * widget) 形参第二项中可以将QCheckBox类型的指针强制转换为QWidget 类型。函数的实质是将小部件widget加入到了控件item之中,并且置顶。另外使用itemWidget()函数可以返回该小部件。 QListWidget * list = new Q
<h3>回答1:</h3><br/>如何在Qt的QListWidget上进行下移动? 在Qt的QListWidget上进行下移动,可以使用QListWidgetItem的下移方法,将选中的项目向下移动一个位置。具体实现可以参考以下代码: QListWidgetItem* selectedItem = ui->listWidget->currentItem(); //获取当前选中的项目 int currentIndex = ui->listWidget->row(selectedItem); //获取当前选中项目的行号 if (currentIndex < ui->listWidget->count() - 1) { //如果当前项目不是最后一个 QListWidgetItem* nextItem = ui->listWidget->item(currentIndex + 1); //获取下一个项目 ui->listWidget->takeItem(currentIndex); //将当前项目从列表中移除 ui->listWidget->insertItem(currentIndex + 1, selectedItem); //将当前项目插入到下一个项目的位置 ui->listWidget->setCurrentItem(selectedItem); //将当前项目设为选中状态 如果需要实现全部选中项目下移一个位置的功能,也可以使用QListWidget的selectedItems()方法获取当前选中的项目列表,逐个进行下移操作。 <h3>回答2:</h3><br/>Qt中QListWidget提供了一种更加灵活,方便的管理item的方式,可以在这个控件上增加、删除、重新排序各种item,本文将针对QListWidget中item的上下移动进行简要说明。 首先,QListWidget的item是可以被拖拽的,也就是可以通过鼠标左键的拖拽操作进行重新排序。但这只是一种视觉上的操作,不会真正影响列表中item的位置,如果需要影响item的位置,需要编写代码实现。 当我们需要通过程序实现上下移动item时,可以通过QListWidget的成员函数进行操作,其调用格式为:`QListWidgetItem *QListWidget::takeItem(int row)`,返回指定row的item,并将其从列表中移除,然后可通过`void QListWidget::insertItem(int row, QListWidgetItem *item)`插入到指定位置。 在这个基础上,我们可以再编写一些简单的代码实现item的上下移动。 例如,当用户按下“上移”按钮时,我们可以将被选中的item向上移动一个位置,具体实现如下: ```c++ QListWidgetItem *item = ui->listWidget->currentItem(); // 获取被选中item if(item) // 如果有选中item int row = ui->listWidget->row(item); // 获取其位置 if(row > 0) // 如果不是第一个 ui->listWidget->takeItem(row); // 移除item ui->listWidget->insertItem(row - 1, item); // 插入到前一个位置 ui->listWidget->setCurrentItem(item); // 选中移动后的item 同样,我们也可以编写“下移”按钮的操作,只需将row - 1改为row + 1即可。 当然,这只是一种简单的实现方式,如果需要更加高效、流畅的操作,可以使用QListWidget的其他接口或自定义item来实现。 总的来说,Qt中QListWidget的上下移动操作并不难实现,只需要理解其基本原理和API接口即可。 <h3>回答3:</h3><br/>在Qt的QListWidget中移动item的操作实现比较方便,可以使用QListWidget自带的API来完成。主要的方法有两个:setCurrentRow()和currentRow()。setCurrentRow()用于设置当前选中的item,currentRow()用于获取当前选中的item的行号。 1. 上下移动的实现 上下移动item一般有两种方式:通过鼠标拖拽或者通过键盘上下键。 通过鼠标拖拽移动item需要重载QListWidget的dragEnterEvent()、dragMoveEvent()和dropEvent()三个方法,这里不多做介绍。 通过键盘上下键移动item,可以响应键盘事件,然后根据按键移动当前选中的item即可。以下是一个简单的示例代码: ```cpp void Widget::keyPressEvent(QKeyEvent *event) int row = listWidget->currentRow(); if (event->key() == Qt::Key_Up) if (row > 0) listWidget->setCurrentRow(row - 1); else if (event->key() == Qt::Key_Down) if (row < listWidget->count() - 1) listWidget->setCurrentRow(row + 1); 在这个示例中,通过判断按下的键是否是上下键,然后根据当前选中的item的行号计算出要移动到的item的行号,最后调用setCurrentRow()方法设置选中的item即可。 2. 移动item的效果 默认情况下,QListWidget中上下移动item只会改变item的位置,不会改变item的外观效果。如果需要给移动item添加一些动画效果,可以通过QPropertyAnimation类来实现。以下是一个简单的示例代码: ```cpp void Widget::keyPressEvent(QKeyEvent *event) int row = listWidget->currentRow(); if (event->key() == Qt::Key_Up) if (row > 0) listWidget->setCurrentRow(row - 1); QPropertyAnimation *animation = new QPropertyAnimation(listWidget->item(row), "pos"); animation->setDuration(300); animation->setEasingCurve(QEasingCurve::OutQuad); animation->setStartValue(QPoint(0, (row + 1) * listWidget->sizeHintForRow(0))); animation->setEndValue(QPoint(0, row * listWidget->sizeHintForRow(0))); animation->start(QAbstractAnimation::DeleteWhenStopped); else if (event->key() == Qt::Key_Down) if (row < listWidget->count() - 1) listWidget->setCurrentRow(row + 1); QPropertyAnimation *animation = new QPropertyAnimation(listWidget->item(row), "pos"); animation->setDuration(300); animation->setEasingCurve(QEasingCurve::OutQuad); animation->setStartValue(QPoint(0, (row - 1) * listWidget->sizeHintForRow(0))); animation->setEndValue(QPoint(0, row * listWidget->sizeHintForRow(0))); animation->start(QAbstractAnimation::DeleteWhenStopped); 在这个示例中,通过QPropertyAnimation类对item的位置进行动画变化,使移动item的过程更加流畅。其中,使用了OutQuad的缓动函数,可以使移动速度呈现加速度效果。具体的实现过程可以根据需求进行调整。