Qt `QComboBox` 内部添加 `QCheckBox`

你希望在 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`,支持多选功能。你可以根据需要进一步自定义或扩展这个实现。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值