Qt提供的QComboBox只支持下拉列表内容的单选,但通过QComboBox提供的setModel、setView、setLineEdit三个方法,可以对QComboBox进行改造,使其实现下拉列表选项的多选。
QComboBox可以看作两个组件的组合:一个QLineEdit和一个QListWidget。QLineEidt是框中显示的内容,QListWidget是下拉列表。我们可以实现QComboBox的子类,在其中自定义QLineEdit和QListWidget,然后通过setModel、setView、setLineEdit三个方法替换QComboBox自带的文本框和下拉列表
class MultiComboBox : public QComboBox {
Q_OBJECT
public:
MultiComboBox(QWidget* parent = nullptr);
void addItem(const QString& text, const QVariant& userData = QVariant()); // 重写父类addItem的方法
public slots:
void stateChangedSlot(int); // 下拉列表中的内容被选中时触发
private:
QListWidget* list;
QLineEdit* edit;
};
MultiComboBox::MultiComboBox(QWidget* parent) : QComboBox(parent) {
edit = new QLineEdit(this);
list = new QListWidget(this);
edit->setReadOnly(true);
this->setModel(list->model());
this->setView(list);
this->setLineEdit(edit);
}
对于我们重新定义的QListWidget,其中包含的每一条内容应该是一个QCheckBox,因此重写QComboBox中的addItem方法,将传入的字符串包装为QCheckBox
void MultiComboBox::addItem(const QString& text, const QVariant& userData) {
QListWidgetItem* item = new QListWidgetItem(list);
QCheckBox* checkBox = new QCheckBox(this);
checkBox->setText(text);
list->addItem(item);
list->setItemWidget(item, checkBox);
connect(checkBox, SIGNAL(stateChanged(int)), this, SLOT(stateChangedSlot(int)));
}
同理,也可以重写addItems方法
当下拉列表中的内容被选中(或取消选中)时,QCheckBox触发stateChanged(int)信号,我们实现一个对应的槽函数,完成MultiComboBox需要实现的逻辑。比如最基本的:将当前选中的内容添加到显示框中
void MultiComboBox::stateChangedSlot(int) {
QString str = "";
for (int i = 0; i < list->count(); i++) {
QCheckBox* cb = static_cast<QCheckBox*>(list->itemWidget(list->item(i)));
if (cb->isChecked()) {
str += cb->text();
str += ";"; // 多个内容以分号隔开
}
}
str = str.removeAt(str.size() - 1);
if (str != "") {
edit->setText(str);
}
else {
edit->clear();
}
}
效果: