Bootstrap

【Qt】重写QComboBox下拉展示多列数据

需求

点击QComboBox时,下拉列表以多行多列的表格展示出来。

实现

直接上代码:

#include <QComboBox>
#include <QTableWidget>
#include <QVBoxLayout>
#include <QWidget>
#include <QEvent>
#include <QMouseEvent>
#include <QLineEdit>
class ComboBoxWithTableWidget : public QComboBox {
    Q_OBJECT

public:
    ComboBoxWithTableWidget(QWidget *parent = nullptr) : QComboBox(parent) {
        // 隐藏默认的下拉箭头
        setEditable(true);
        lineEdit()->setReadOnly(true);

        // 创建一个隐藏的容器来存放我们的表格
        popupWidget = new QWidget(this);
        popupWidget->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint);

        QVBoxLayout *layout = new QVBoxLayout(popupWidget);
        layout->setContentsMargins(0, 0, 0, 0);
        layout->setSpacing(0);

        tableWidget = new QTableWidget(5, 2, popupWidget); // 5行2列
        for (int row = 0; row < 5; ++row)
        {
            for (int col = 0; col < 2; ++col)
            {
                QTableWidgetItem *item = new QTableWidgetItem(QString("Item %1%2").arg(row).arg(col));
                tableWidget->setItem(row, col, item);
            }
        }
        tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
        tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
        layout->addWidget(tableWidget);
        popupWidget->resize(220,200);

        connect(tableWidget, &QTableWidget::cellClicked, this, &ComboBoxWithTableWidget::onCellClicked);

        popupWidget->hide();
    }

protected:

    void showPopup() override
    {
        if (popupWidget->isHidden())
        {
            QComboBox::showPopup();

            //popupWidget->resize(this->width(), tableWidget->height() + 2); //(可能需要调整)
            popupWidget->move(this->mapToGlobal(QPoint(0, this->height())));
            popupWidget->show();

            tableWidget->setFocus();
        }
    }

    void hidePopup() override
    {
        if (popupWidget->isVisible())
        {
            popupWidget->hide();
            QComboBox::hidePopup();
        }
    }

private slots:
    void onCellClicked(int row, int column)
    {
        QString text = tableWidget->item(row, column)->text();
        this->setCurrentText(text);
        hidePopup(); // 选择后隐藏下拉列表
    }

private:
    QWidget *popupWidget = nullptr;
    QTableWidget *tableWidget= nullptr;
};

示例效果

;