gpt4 book ai didi

c++ - 自定义 QTableView 网格样式

转载 作者:太空狗 更新时间:2023-10-29 21:09:56 26 4
gpt4 key购买 nike

我想知道几件事。我已将 QTableView 子类化以制作自定义表格。我希望能够做几件事。

首先,我不希望选定的单元格都具有“选定”颜色(默认情况下为蓝色),而是在选定的单元格周围有一个框架(就像在 Excel 中一样)。为此,我使用了以下内容(在我的自定义 QItemDelegate 中):

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QModelIndex upIndex = index.sibling(index.row() - 1, index.column());
QModelIndex downIndex = index.sibling(index.row() + 1, index.column());
QModelIndex rightIndex = index.sibling(index.row(), index.column() + 1);
QModelIndex leftIndex = index.sibling(index.row(), index.column() - 1);

auto newOption = option;
if (option.state.testFlag(QStyle::State_Selected))
{
painter->save();

auto selIndexes = selM->selectedIndexes().toSet();
painter->setPen(QPen(Qt::red, 5));
if (!selIndexes.contains(rightIndex))
painter->drawLine(option.rect.topRight(), option.rect.bottomRight());
if (!selIndexes.contains(upIndex))
painter->drawLine(option.rect.topLeft(), option.rect.topRight());
if (!selIndexes.contains(downIndex))
painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
if (!selIndexes.contains(leftIndex))
painter->drawLine(option.rect.topLeft(), option.rect.bottomLeft());

painter->restore();
// newOption.palette.setBrush(QPalette::Normal, QPalette::Highlight, index.data(Qt::BackgroundRole).value<QColor>());
newOption.palette.setBrush(QPalette::Normal, QPalette::Highlight, Qt::gray);
}
QStyledItemDelegate::paint(painter, newOption, index);
}

这可能不是最优的,但我希望先有一些有用的东西。

现在它似乎可以正常工作,但不幸的是它不会自动重绘。当我选择单元格时会发生以下情况:

Incorrect

这根本不是我要找的。我猜它没有被重绘,因为 (1) 区域内的点仍然是红色的,并且 (2) 如果我调整窗口大小,我会得到以下信息:

Kind of correct

这更接近我想要实现的目标。

我已经尝试在我的 QTableView 中这样做:

// selModel is my selection model
connect(selModel, &QItemSelectionModel::selectionChanged, [this]() {
for(const auto & selected : selModel->selectedIndexes())
{
update(visualRect(selected));
repaint(visualRect(selected));
}
}

(之前,我实际上使用了 setDirtyRegion 但它也没有用,所以我想我会做一些更......残酷的事情。)

最后,我还有一个问题:为什么我的手机角落里会出现那些奇怪的红色“细线”?即使在“某种”正确的屏幕截图上,我也得到了无法解释的这些行:

Small lines

如果您对任何问题有任何想法,请提出建议。

最佳答案

这个问题很容易解释如下。

假设单元格 (0,0) 被选中。现在用户选择额外的单元格 (0,1)、(1,0) 和 (1,1)。 Qt 正确地重新绘制了额外的 3 个单元格,即被选中了。但是,它不会重新绘制单元格 (0,0),因为它既不是选择或取消选择。当然,对于您想要的行为,您仍然需要重新绘制此单元格。

这可以通过重绘当前选择的所有索引轻松实现。

MyDelegate.h

#pragma once

#include <QStyledItemDelegate>
#include <QItemSelectionModel>

class MyDelegate : public QStyledItemDelegate {

public:
virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;

void setSelectionModel(QItemSelectionModel* selectionModel);
private:
QItemSelectionModel* mSelectionModel{ nullptr };
};

MyDelegate.cpp

#include "MyDelegate.h"
#include <QPainter>
#include <QDebug>

void MyDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (!mSelectionModel) return;
auto newOption = option;
auto normalText = newOption.palette.brush(QPalette::ColorGroup::Normal, QPalette::ColorRole::Text);
newOption.palette.setBrush(QPalette::ColorGroup::Normal, QPalette::ColorRole::Highlight, QBrush(Qt::GlobalColor::blue, Qt::BrushStyle::NoBrush));
newOption.palette.setBrush(QPalette::ColorGroup::Normal, QPalette::ColorRole::HighlightedText, normalText);
QStyledItemDelegate::paint(painter, newOption, index);
QModelIndex upIndex = index.sibling(index.row() - 1, index.column());
QModelIndex downIndex = index.sibling(index.row() + 1, index.column());
QModelIndex rightIndex = index.sibling(index.row(), index.column() + 1);
QModelIndex leftIndex = index.sibling(index.row(), index.column() - 1);
//auto newOption = option;
//newOption.palette.setBrush(QPalette::Normal, QPalette::Highlight, Qt::transparent);
if (option.state.testFlag(QStyle::State_Selected))
{
painter->save();
painter->setClipRect(option.rect);
auto selIndexes = mSelectionModel->selectedIndexes().toSet();
painter->setPen(QPen(Qt::red, 5));
if (!selIndexes.contains(rightIndex))
painter->drawLine(option.rect.topRight(), option.rect.bottomRight());
if (!selIndexes.contains(upIndex))
painter->drawLine(option.rect.topLeft(), option.rect.topRight());
if (!selIndexes.contains(downIndex))
painter->drawLine(option.rect.bottomLeft(), option.rect.bottomRight());
if (!selIndexes.contains(leftIndex))
painter->drawLine(option.rect.topLeft(), option.rect.bottomLeft());

painter->restore();
}
}

void MyDelegate::setSelectionModel(QItemSelectionModel* selectionModel)
{
mSelectionModel=selectionModel;
}

main.cpp

#include <QApplication>
#include <QDebug>
#include <QStandardItemModel>
#include <QTableWidget>
#include "MyDelegate.h"

int main(int argc, char** args) {
QApplication app(argc, args);
auto widget = new QTableView;
QStandardItemModel model;
model.setRowCount(10);
model.setColumnCount(10);
for (auto i = 0; i < 10; i++) {
for (auto j = 0; j < 10; j++) {
model.setItem(i, j, new QStandardItem("Test"));
}
}
auto selModel = new QItemSelectionModel;
selModel->setModel(&model);
widget->setModel(&model);
widget->setSelectionModel(selModel);

auto delegate = new MyDelegate;
delegate->setSelectionModel(selModel);
widget->setItemDelegate(delegate);
// Ensures that also items are repainted, that where neither selected nor deselect, but will stay selected
// This solutions eventually paints elements twice
QObject::connect(selModel, &QItemSelectionModel::selectionChanged, [widget,selModel](auto &selected, auto& deselected) {
for (auto item : selModel->selectedIndexes()) {
widget->update(item);
}
});
widget->show();
app.exec();
}

至于奇怪的红线伪像,我猜你应该在允许的矩形内绘制红线。这很容易通过裁剪到项目边界来实现。

关于c++ - 自定义 QTableView 网格样式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56491637/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com