你希望在 QComboBox 内部添加 QCheckBox 并支持多选。这里有一个更加符合你需求的实现。我们将创建一个自定义的 QComboBox 子类来实现这个功能。
以下是完整的代码:
### checkablecombobox.h
```h
#ifndef CHECKABLECOMBOBOX_H
#define CHECKABLECOMBOBOX_H
#include <QComboBox>
#include <QStandardItemModel>
class CheckableComboBox : public QComboBox
{
Q_OBJECT
public:
explicit CheckableComboBox(QWidget *parent = nullptr);
void addItem(const QString &text, const QVariant &userData = QVariant());
void addItems(const QStringList &texts);
QStringList currentItems() const;
protected:
bool eventFilter(QObject *object, QEvent *event) override;
void showPopup() override;
void hidePopup() override;
private:
QStandardItemModel *model;
void updateText();
void setChecked(int index, bool checked);
private slots:
void itemChanged(QStandardItem *item);
void onActivated(int index);
};
#endif // CHECKABLECOMBOBOX_H
```
### checkablecombobox.cpp
```cpp
#include "checkablecombobox.h"
#include <QLineEdit>
#include <QEvent>
#include <QListView>
#include <QMouseEvent>
CheckableComboBox::CheckableComboBox(QWidget *parent)
: QComboBox(parent)
{
model = new QStandardItemModel(this);
setModel(model);
setEditable(true);
lineEdit()->setReadOnly(true);
QListView *listView = new QListView(this);
setView(listView);
listView->setModelColumn(0);
listView->viewport()->installEventFilter(this);
connect(model, &QStandardItemModel::itemChanged, this, &CheckableComboBox::itemChanged);
connect(this, QOverload<int>::of(&QComboBox::activated), this, &CheckableComboBox::onActivated);
}
void CheckableComboBox::addItem(const QString &text, const QVariant &userData)
{
QStandardItem *item = new QStandardItem(text);
item->setCheckable(true);
item->setCheckState(Qt::Unchecked);
if (userData.isValid()) {
item->setData(userData, Qt::UserRole);
}
model->appendRow(item);
updateText();
}
void CheckableComboBox::addItems(const QStringList &texts)
{
for (const QString &text : texts) {
addItem(text);
}
}
QStringList CheckableComboBox::currentItems() const
{
QStringList items;
for (int i = 0; i < model->rowCount(); ++i) {
QStandardItem *item = model->item(i);
if (item->checkState() == Qt::Checked) {
items << item->text();
}
}
return items;
}
bool CheckableComboBox::eventFilter(QObject *object, QEvent *event)
{
if (object == view()->viewport() && event->type() == QEvent::MouseButtonRelease) {
QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
QModelIndex index = view()->indexAt(mouseEvent->pos());
if (index.isValid()) {
setChecked(index.row(), model->item(index.row())->checkState() == Qt::Unchecked);
return true;
}
}
return false;
}
void CheckableComboBox::showPopup()
{
QComboBox::showPopup();
QListView *listView = qobject_cast<QListView*>(view());
if (listView) {
listView->setMinimumWidth(width());
}
}
void CheckableComboBox::hidePopup()
{
QComboBox::hidePopup();
updateText();
}
void CheckableComboBox::updateText()
{
QStringList selectedItems = currentItems();
if (selectedItems.isEmpty()) {
setEditText("Select items...");
} else {
setEditText(selectedItems.join(", "));
}
}
void CheckableComboBox::setChecked(int index, bool checked)
{
QStandardItem *item = model->item(index);
if (item) {
item->setCheckState(checked ? Qt::Checked : Qt::Unchecked);
}
updateText();
}
void CheckableComboBox::itemChanged(QStandardItem *item)
{
Q_UNUSED(item);
updateText();
}
void CheckableComboBox::onActivated(int index)
{
setChecked(index, model->item(index)->checkState() == Qt::Unchecked);
}
```
### mainwindow.h
```h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "checkablecombobox.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
CheckableComboBox *comboBox;
};
#endif // MAINWINDOW_H
```
### mainwindow.cpp
```cpp
#include "mainwindow.h"
#include <QVBoxLayout>
#include <QPushButton>
#include <QMessageBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QWidget *centralWidget = new QWidget(this);
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
comboBox = new CheckableComboBox(this);
comboBox->addItems({"Option 1", "Option 2", "Option 3", "Option 4"});
QPushButton *button = new QPushButton("Show Selected Items", this);
connect(button, &QPushButton::clicked, this, [this]() {
QStringList selectedItems = comboBox->currentItems();
QMessageBox::information(this, "Selected Items", selectedItems.join(", "));
});
layout->addWidget(comboBox);
layout->addWidget(button);
setCentralWidget(centralWidget);
}
MainWindow::~MainWindow()
{
}
```
### main.cpp
```cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
```
### CMakeLists.txt
```cmake
cmake_minimum_required(VERSION 3.5)
project(CheckableComboBoxExample LANGUAGES CXX)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Widgets)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets)
add_executable(CheckableComboBoxExample
main.cpp
mainwindow.cpp
mainwindow.h
checkablecombobox.cpp
checkablecombobox.h
)
target_link_libraries(CheckableComboBoxExample PRIVATE Qt${QT_VERSION_MAJOR}::Widgets)
```
这个实现提供了以下功能:
1. 创建了一个自定义的 `CheckableComboBox` 类,它是 `QComboBox` 的子类。
2. `CheckableComboBox` 内部的每个项目都有一个复选框。
3. 用户可以选择多个项目。
4. 当前选中的项目会显示在 ComboBox 的文本区域中。
5. 提供了一个按钮来显示当前选中的项目。
要编译和运行这个程序,请按照以下步骤操作:
1. 创建一个新目录并将上述所有文件放入其中。
2. 打开终端,导航到该目录。
3. 运行以下命令:
```sh
mkdir build
cd build
cmake ..
make
./CheckableComboBoxExample
```
这个实现应该能够满足你的需求,提供了一个带有复选框的 `QComboBox`,支持多选功能。你可以根据需要进一步自定义或扩展这个实现。