我正在开发一个使用 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"
单击“保存”,选择“Emily”,按城市排序(有代理,因此已处理),然后单击“恢复”。虽然它确实取消选择 Emily 并重新选择 Bob 和 Alice,但线条是灰色而不是蓝色:
我在Qt论坛上找到了一个answer,其中提到除了选择之外还有索引。我也尝试更改它(请参阅调用
setCurrentIndex
的注释行),但它也不起作用(并且它只支持单行,而我需要能够选择多行)。
我已经没有主意了。这是一个错误吗?
您所看到的是一个unfocused小部件的选择。使用带有某些选定文本的 QTextEdit 或 QPlainTextEdit,然后单击其他一些小部件,您会看到类似的结果:一旦小部件失去焦点,选择内容也会同样变成灰色。
style()
(或小部件)绘制 UI,它尝试遵循操作系统配置(至少在 Windows 和 macOS 上),最终考虑系统/应用程序/小部件调色板.
默认情况下,Windows 行为显示
Highlight
颜色角色(用作选择的背景),考虑到 颜色组 通常基于小部件及其父级(包括窗口)的当前焦点状态.
在标准配置中,Windows 上的突出显示颜色对于活动小部件来说是蓝色阴影,对于不活动/未聚焦的小部件来说是浅灰色。
focusPolicy
,即 Qt::StrongFocus
),这意味着任何先前 焦点 小部件可能会变成 Inactive
。
视图的选择会变成灰色,因为焦点被按钮“窃取”了。请注意,当您单击“保存”按钮时也会发生这种情况。
setFocus()
。
或者,您可以通过使用
setFocusPolicy()
与 Qt::NoFocus
或 Qt::TabFocus
(如果您想保留选项卡导航)来覆盖按钮的焦点策略。
请注意,焦点和焦点感知颜色是桌面 UI 的基本方面,应始终仔细考虑。由于您不了解这些方面,我强烈建议您对这些主题进行更多研究,包括 QPalette/QStyle 文档和通用 UI 约定。
您也可以查看这个相关问题我过去曾提出过;它基于 Python,但概念仍然存在,并且代码对于 C++ 开发人员来说很容易理解。