复选框的组合框?

24
我正在尝试使 ComboBox 中的项目可选。我尝试了这个方法:http://programmingexamples.net/wiki/Qt/ModelView/ComboBoxOfCheckBoxes, 其中我继承了 QStandardItemModel 并重新实现了 flags() 函数以使项目可选。然后我将此模型添加到 ComboBox 中。不幸的是,在项目中未出现复选框。有谁能看出我哪里错了吗?
4个回答

23

你是否设置了检查状态并将它们标记为可选中?

在我的下面的例子中,这一行非常关键:

item->setData(Qt::Unchecked, Qt::CheckStateRole);
如果省略它,复选框将无法渲染,因为没有有效的检查状态可供渲染。
该示例显示了组合框、列表和表格中的复选框,因为一开始我也无法使其正常工作,所以我尝试了不同的视图。 test.cpp
#include <QtGui>

int main(int argc, char** argv)
{
    QApplication app(argc, argv);

    QStandardItemModel model(3, 1); // 3 rows, 1 col
    for (int r = 0; r < 3; ++r)
    {
        QStandardItem* item = new QStandardItem(QString("Item %0").arg(r));

        item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
        item->setData(Qt::Unchecked, Qt::CheckStateRole);

        model.setItem(r, 0, item);
    }

    QComboBox* combo = new QComboBox();
    combo->setModel(&model);

    QListView* list = new QListView();
    list->setModel(&model);

    QTableView* table = new QTableView();
    table->setModel(&model);

    QWidget container;
    QVBoxLayout* containerLayout = new QVBoxLayout();
    container.setLayout(containerLayout);
    containerLayout->addWidget(combo);
    containerLayout->addWidget(list);
    containerLayout->addWidget(table);

    container.show();

    return app.exec();
}

test.pro

QT=core gui
SOURCES=test.cpp

2
太棒了 - 这确实解决了问题!现在,如果我想将复选框的信号之一连接到插槽(比如clicked()),以查看它何时被单击并且是否被选中,我该怎么做?QStandardItem没有从QObject派生,因此它不能具有信号。我查看了QComboBox的信号 - 当我悬停在新复选框上时,会发出highlighted()信号,但是当我单击复选框时似乎没有任何信号被发出?我尝试将Qt :: ItemIsSelectable添加到项目的标志中,然后发出combobox :: currentIndexChanged信号,但是组合框会关闭,这不是我想要的。有什么想法吗? - David Doria
1
你需要在模型中完成这个任务,子类化QAbstractListModel并实现rowCountdataflagssetData方法。确保模型处理Qt::CheckStateRole角色。在setData方法中,你可以触发信号,因为模型是QObject派生的。 - Silas Parker
2
这甚至比那更容易 :). 不需要任何子类化: connect(this->Model, SIGNAL(dataChanged ( const QModelIndex&, const QModelIndex&)), this, SLOT(slot_changed()));与:void MainWindow::slot_changed() { std::cout << "已高亮显示。" << std::endl; if(this->Item->checkState() == Qt::Unchecked) { std::cout << "未选中!" << std::endl; } else if(this->Item->checkState() == Qt::Checked) { std::cout << "已选中!" << std::endl; }} - David Doria
工作示例可在此处找到:http://programmingexamples.net/wiki/Qt/ModelView/ComboBoxOfCheckBoxes - David Doria

17

我有一个小的补充。

如果在Mac OS X上编译skyhisi的代码,则组合框(combobox)看起来不像原生复选框的组合框。您可以在截图中看到。

enter image description here

测试使用的是 qt-4.8.5 和 5.1.1。

看起来 Qt 是自己绘制这些控件。我们的团队无意中发现了以下解决方法。您可以子类化 QStyledItemDelegate 并以以下方式重新实现 paint()

void SubclassOfQStyledItemDelegate::paint(QPainter * painter_, const QStyleOptionViewItem & option_, const QModelIndex & index_) const
{
    QStyleOptionViewItem & refToNonConstOption = const_cast<QStyleOptionViewItem &>(option_);
    refToNonConstOption.showDecorationSelected = false;
    //refToNonConstOption.state &= ~QStyle::State_HasFocus & ~QStyle::State_MouseOver;

    QStyledItemDelegate::paint(painter_, refToNonConstOption, index_);
}

您可以通过将以下代码添加到skyhisi的代码中,将此委托设置为组合框:

SubclassOfQStyledItemDelegate *delegate = new SubclassOfQStyledItemDelegate(this);
combo->setItemDelegate(delegate);

此委托安装的comboBox外观如下: enter image description here

在Windows上可能会出现不同的问题:复选框的文本具有固定的背景或项目周围的点状边框:

enter image description here

要更改此外观,可以在覆盖的 paint 函数中在 QStyledItemDelegate::paint(painter_, refToNonConstOption, index_) 之前添加以下行(在代码示例中,此行被注释):

refToNonConstOption.state &= ~QStyle::State_HasFocus & ~QStyle::State_MouseOver;

结果:

在此输入图片描述


2
嗨,由于comboBox(Windows示例)中存在多个选择,显示“Item 0”文本就没有意义了。有没有一种方法可以禁用该文本或将其更改为“请选择项目”之类的内容? - Aleksandar
1
@Aleksandar 或者我们应该看到“Item1,Item2”而不是可能*未被选中的“Item 0”:组合框中所有选定项目的串联。有人知道这是否可行吗? - yves Baumes
1
@yvesBaumes 我创建了一个 QComboBox 的子类,根据选择更新可见文本(以及其他一些功能)。https://gist.github.com/mistic100/c3b7f3eabc65309687153fe3e0a9a720 - Mistic

1

我尝试在Linux Mint上制作这个示例,但是我无法使复选框可见。我不得不实现SubclassOfQStyledItemDelegate类并将委托设置为Neptilo和gshep建议的复选框。


1
您可以尝试使用 QListView 进行此操作:
QStringList values = QStringList << "check 1" << "check 2" << "check 3" << "check 4";

QStandardItemModel model = new QStandardItemModel;
for (int i = 0; i < values.count(); i++)
{
    QStandardItem *item = new QStandardItem();
    item->setText(values[i]);
    item->setCheckable(true);
    item->setCheckState(Qt::Unchecked);
    model->setItem(i, item);
}

ui->list->setModel(model);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接