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();}
}
效果: