QTableView 以蓝色显示选定的行,但使用 QItemSelectionModel::select 它们会变成灰色

问题描述 投票:0回答:1

我正在开发一个使用 Qt 6.6.1 来显示表格的 C++ 程序。

可以单击行来选择它们,在这种情况下,它们会以蓝色突出显示(可能颜色是特定于操作系统的;我使用的是 Windows 10)。在某个时刻,我必须能够保存该选择,稍后我必须恢复它。我已经几乎设法做到了,但是当我恢复选择时,这些线以灰色突出显示,而不是蓝色。我不明白为什么,我想知道如何解决它。

这是一个最小的示例,编写为单个文件以使其更容易重现:

#include <QApplication>
#include <QTableView>
#include <QStandardItemModel>
#include <QSortFilterProxyModel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>
#include <QGuiApplication>
#include <QScreen>

class TableViewExample : public QWidget
{
    Q_OBJECT

public:
    TableViewExample(QWidget *parent = nullptr)
        : QWidget(parent)
    {
        // Create a custom TableModel
        model = new QStandardItemModel(0, 3, this);
        model->setHeaderData(0, Qt::Horizontal, "Name");
        model->setHeaderData(1, Qt::Horizontal, "Age");
        model->setHeaderData(2, Qt::Horizontal, "City");

        // Populate the model with some rows
        model->appendRow({ new QStandardItem("Alice"),   new QStandardItem("30"), new QStandardItem("London") });
        model->appendRow({ new QStandardItem("Bob"),     new QStandardItem("35"), new QStandardItem("Paris")  });
        model->appendRow({ new QStandardItem("Charles"), new QStandardItem("18"), new QStandardItem("Rome")   });
        model->appendRow({ new QStandardItem("Dave"),    new QStandardItem("28"), new QStandardItem("Berlin") });
        model->appendRow({ new QStandardItem("Emily"),   new QStandardItem("40"), new QStandardItem("Madrid") });

        // Create a QSortFilterProxyModel and set the source model
        proxyModel = new QSortFilterProxyModel(this);
        proxyModel->setSourceModel(model);

        // Create a QTableView and set the proxy model as its model
        tableView = new QTableView(this);
        tableView->setModel(proxyModel);
        tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
        tableView->setSortingEnabled(true);

        // Create buttons for saving and restoring the selection
        QPushButton* saveButton    = new QPushButton("Save Selection", this);
        QPushButton* restoreButton = new QPushButton("Restore Selection", this);

        // Connect the buttons to functions
        connect(saveButton,    &QPushButton::clicked, this, &TableViewExample::saveSelection);
        connect(restoreButton, &QPushButton::clicked, this, &TableViewExample::restoreSelection);

        // Create a layout and add the table view and buttons
        QVBoxLayout* layout = new QVBoxLayout(this);
        layout->addWidget(tableView);
        layout->addWidget(saveButton);
        layout->addWidget(restoreButton);

        setLayout(layout);

        // Make the window large enough to avoid scrollbars
        setGeometry(100, 100, 340, 260);

        // Center on screen
        setGeometry( QStyle::alignedRect( Qt::LeftToRight,
                                          Qt::AlignCenter,
                                          size(),
                                          QGuiApplication::primaryScreen()->availableGeometry() ) );
    }

private slots:
    void saveSelection()
    {
        savedSourceIndices.clear();
        QModelIndexList proxyIndices = tableView->selectionModel()->selectedIndexes();

        for (const QModelIndex& proxyIndex : proxyIndices) {
            QModelIndex sourceIndex = proxyModel->mapToSource(proxyIndex);
            savedSourceIndices.append(sourceIndex);
        }
    }

    void restoreSelection()
    {
        tableView->selectionModel()->clearSelection();

        for (const QModelIndex& savedIndex : savedSourceIndices)
        {
            tableView->selectionModel()->select(proxyModel->mapFromSource(savedIndex), QItemSelectionModel::Select);
            //tableView->setCurrentIndex(proxyModel->mapFromSource(savedIndex));
        }
    }

private:
    QTableView* tableView;
    QStandardItemModel* model;
    QSortFilterProxyModel* proxyModel;
    QModelIndexList savedSourceIndices;
};

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

    TableViewExample example;
    example.show();

    return app.exec();
}

#include "main.moc"

例如,选择 Bob 和 Alice:他们的线条是蓝色的。
The selection I save, with lines highlighted in blue

单击“保存”,选择“Emily”,按城市排序(有代理,因此已处理),然后单击“恢复”。虽然它确实取消选择 Emily 并重新选择 Bob 和 Alice,但线条是灰色而不是蓝色:
The restored selection, with lines highlighted in grey

我在Qt论坛上找到了一个answer,其中提到除了选择之外还有索引。我也尝试更改它(请参阅调用

setCurrentIndex
的注释行),但它也不起作用(并且它只支持单行,而我需要能够选择多行)。

我已经没有主意了。这是一个错误吗?

c++ qt selection qtableview
1个回答
0
投票

您所看到的是一个unfocused小部件的选择。使用带有某些选定文本的 QTextEdit 或 QPlainTextEdit,然后单击其他一些小部件,您会看到类似的结果:一旦小部件失去焦点,选择内容也会同样变成灰色。

Qt 根据应用程序

style()
(或小部件)绘制 UI,它尝试遵循操作系统配置(至少在 Windows 和 macOS 上),最终考虑系统/应用程序/小部件调色板.

默认情况下,Windows 行为显示

Highlight
颜色角色(用作选择的背景),考虑到 颜色组 通常基于小部件及其父级(包括窗口)的当前焦点状态.

在标准配置中,Windows 上的突出显示颜色对于活动小部件来说是蓝色阴影,对于不活动/未聚焦的小部件来说是浅灰色。

当单击按钮时,它通常会获得焦点(由于默认为

focusPolicy
,即
Qt::StrongFocus
),这意味着任何先前 焦点 小部件可能会变成
Inactive

视图的选择会变成灰色,因为焦点被按钮“窃取”了。请注意,当您单击“保存”按钮时也会发生这种情况。

最简单的解决方案是在连接到按钮的插槽内的视图上调用

setFocus()

或者,您可以通过使用

setFocusPolicy()
Qt::NoFocus
Qt::TabFocus
(如果您想保留选项卡导航)来覆盖按钮的焦点策略。

请注意,焦点和焦点感知颜色是桌面 UI 的基本方面,应始终仔细考虑。由于您不了解这些方面,我强烈建议您对这些主题进行更多研究,包括 QPalette/QStyle 文档和通用 UI 约定。

您也可以查看这个相关问题我过去曾提出过;它基于 Python,但概念仍然存在,并且代码对于 C++ 开发人员来说很容易理解。

© www.soinside.com 2019 - 2024. All rights reserved.