背景
在项目开发过程中需要使 QComboBox 下拉一个树形列表,直接通过 setModel 和 setView 设置 combox 控件可以实现,但是在单击节点箭头按钮时也会隐藏下拉框的显示。因此需要重新实现 QComboBox 的方法来实现自己控制。
①.通过 QTreeComboBoxView子类化 QTreeWidget 类,以重写 mousePressEvent 事件自己实现节点的展开和收缩,否则会有事件冲突。
②.通过 QTreeListComboBox 子类化 QComboBox 类,以重写 hidePopup 方法,判断条件是否满足。
QTreeComboBoxView
class QTreeComboBoxView : public QTreeWidget
{
Q_OBJECT
public:
QTreeComboBoxView(QWidget *parent = Q_NULLPTR) :QTreeWidget(parent) {}
~QTreeComboBoxView() {};
protected:
void mousePressEvent(QMouseEvent *event) override;
signals:
void treeMousePressed(bool inItem);
};
void QTreeComboBoxView::mousePressEvent(QMouseEvent *event)
{
auto curIndex = currentIndex();
auto rect = this->visualRect(curIndex);
auto buttonRect = QRect(rect.left() - 20, rect.top(), 20, rect.height());
if (buttonRect.contains(event->pos()))
{
if (isExpanded(curIndex)) setExpanded(curIndex, false);
else setExpanded(curIndex, true);
emit treeMousePressed( true );
}
else
emit treeMousePressed(false);
}
QTreeListComboBox
class QTreeListComboBox : public QComboBox
{
Q_OBJECT
public:
QTreeListComboBox( QWidget *parent = Q_NULLPTR);
~QTreeListComboBox() {};
protected:
void hidePopup() override;
private:
bool canHidePopup = true;//允许收缩
public:
QTreeComboBoxView * displayTreeWidget = nullptr;
private:
Ui::QTreeListComboBox ui;
};
QTreeListComboBox::QTreeListComboBox( QWidget *parent)
: QComboBox(parent)
{
ui.setupUi(this);
displayTreeWidget = new QTreeComboBoxView(this);
displayTreeWidget->setSelectionMode(QAbstractItemView::SingleSelection);
displayTreeWidget->setHeaderHidden(true);
this->setModel(displayTreeWidget->model());
this->setView(displayTreeWidget);
connect(displayTreeWidget, &QTreeComboBoxView::treeMousePressed, [&](bool inItem) {
canHidePopup = !inItem;
});
connect(this, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated), this, [&](int index) {
hidePopup();
});
}
void QTreeListComboBox::hidePopup()
{
if (canHidePopup) QComboBox::hidePopup();
}
设置分组节点禁止选择
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
代码示例
auto tree = ui.comboBox->displayTreeWidget;
for (int i = 1;i < 4;i++ )
{
QTreeWidgetItem* item = new QTreeWidgetItem(tree, { QString::number(i) });
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
for (int j = 1; j < 5; j++)
{
QTreeWidgetItem* sub = new QTreeWidgetItem(item, { QString("%1.%2").arg(i).arg(j) });
}
}