gpt4 book ai didi

c++ - 如何将原始复选框与 QHeaderView 列标题的中心对齐?

转载 作者:搜寻专家 更新时间:2023-10-31 02:05:01 25 4
gpt4 key购买 nike

我有一个带有自定义 QHeaderView 的自定义 QTableView 模型,以便呈现用于对表格内容执行“全选”功能的复选框。

在我的 header 重载的 paintSection() 函数中,我成功地渲染了用于全选的复选框:

QStyleOptionButton option;
option.rect = QRect(3,10,16,16);
option.state = QStyle::State_Enabled | QStyle::State_Active;
if (isChecked_)
option.state |= QStyle::State_On;
else
option.state |= QStyle::State_Off;
style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter);

不幸的是,复选框呈现为居中,而是左对齐。这与每个表条目的列中正确居中的 QStyledItemDelegate 复选框完全冲突。

我知道我可以更改 QRect 的前两个参数来更改绘制基元的原点,但这对列宽的变化没有反应。虽然,固定列宽并不是最糟糕的解决方案。

如何正确地将列标题中的复选框居中?

辅助问题:标题中的复选框可以通过单击单元格中的任何地方来切换,而不仅仅是在框本身上(与通过委托(delegate)呈现在表格中的那些不同)。有办法解决这个问题吗?

最佳答案

The solution of @scopchanov对我不起作用,因为复选框覆盖了标题的整个项目

enter image description here enter image description here

一个可能的解决方案是用样式绘制 CheckBox,但除此之外,您必须记住该元素是否被选中,为此我们使用 QMap<> , 第一个元素是 logicalIndex因为即使移动列它也不会改变,第二个元素是状态。

#include <QApplication>
#include <QHeaderView>
#include <QMouseEvent>
#include <QPainter>
#include <QStandardItemModel>
#include <QTableView>

class CheckedHeaderView : public QHeaderView
{
Q_OBJECT
public:
using QHeaderView::QHeaderView;
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
QStyleOptionButton opt;

QRect checkbox_rect = style()->subElementRect(QStyle::SE_CheckBoxIndicator, &opt);
checkbox_rect.moveCenter(rect.center());
opt.rect = checkbox_rect;
opt.state = QStyle::State_Enabled | QStyle::State_Active;
if(logicalIndex == columnDown)
opt.state |= QStyle::State_Sunken;
if (states[logicalIndex])
opt.state |= QStyle::State_On;
else
opt.state |= QStyle::State_Off;
style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, painter);
}
void mousePressEvent(QMouseEvent *event) override
{
QHeaderView::mousePressEvent(event);
int li = logicalIndexAt(event->pos());
if(li == -1) return;
columnDown = li;
updateSection(li);
}
void mouseReleaseEvent(QMouseEvent *event) override
{
QHeaderView::mouseReleaseEvent(event);
int li = logicalIndexAt(event->pos());
if(li == -1) return;
states[li] = !states[li];
Q_EMIT checked(li, states[li]);
columnDown = -1;
updateSection(li);
}
Q_SIGNALS:
void checked(int logicalIndex, bool state);
private:
QMap<int, bool> states;
int columnDown = -1;
};

class TableView : public QTableView
{
Q_OBJECT
public:
TableView(QWidget *parent = nullptr):
QTableView(parent)
{
CheckedHeaderView *header = new CheckedHeaderView(Qt::Horizontal, this);
setHorizontalHeader(header);
connect(header, &CheckedHeaderView::checked, this, &TableView::on_checked);
}
private Q_SLOTS:
void on_checked(int logicalIndex, bool state){
QItemSelectionModel::SelectionFlags command = state? QItemSelectionModel::Select : QItemSelectionModel::Deselect;
for(int r=0; r < model()->rowCount(); r++){
QModelIndex ix = model()->index(r, logicalIndex);
selectionModel()->select(ix, command);
}
}
};


int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TableView w;
QStandardItemModel *model = new QStandardItemModel(8, 6, &w);
w.setModel(model);
w.show();
return a.exec();
}

enter image description here

关于c++ - 如何将原始复选框与 QHeaderView 列标题的中心对齐?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52620156/

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