带有小部件和文本的 QStandardItemModel 标头

Posted

技术标签:

【中文标题】带有小部件和文本的 QStandardItemModel 标头【英文标题】:QStandardItemModel header with widget and text 【发布时间】:2013-12-26 22:32:21 【问题描述】:

我需要使用带有文本的复选框,例如“检查所有”:

在 QStandardItemModel 的标头中。我试过这样

QStandardItem* item0 = new QStandardItem("some text");
item0->setCheckable(true);
item0->setCheckState(Qt::Checked);
item0->setText("some text");

_model->setHorizontalHeaderItem(1, item0);

这种方式只适用于不适用于标题的项目,我的意思是如果我使用项目,则适用于

_model->setItem(new QStandardItem(some_item);

我听说要编写自己的继承 QHeaderView 的类,但我不知道这是否有助于解决我的问题。我想问是否有一种简单的方法可以实现这一目标?

问候

【问题讨论】:

不为标头工作到底是什么意思?你在视觉上看到了什么?您能否解释一下和/或附上屏幕截图?您能否发布一个独立的示例来重现该问题?请参考 sscce.org。 对不起。首先,我使用的是 qt 5.2。这不起作用,因为它只显示没有小部件的文本。示例代码我稍后会发布。回答问题 【参考方案1】:

我做了这样的事情:

QStandardItemModel *model = new QStandardItemModel(this);

ui->tableView->setModel(model);

QtCheckHeaderView *header = new QtCheckHeaderView(Qt::Horizontal, ui->tableView);


QtCheckHeaderView *vheader = new QtCheckHeaderView(Qt::Vertical, ui->tableView);

ui->tableView->setHorizontalHeader(header);
ui->tableView->setVerticalHeader(vheader);

QStandardItem *root = model->invisibleRootItem();
QList<QList<QStandardItem *> > items;
for (int i = 0; i < 10; ++i)

    QList<QStandardItem *> res;
    for (int j = 0; j < 1000; ++j)
    
        res.append(new QStandardItem(QString("%1;%2").arg(j).arg(i)));
        vheader->addCheckable(j);
    
    items.append(res);
    root->appendColumn(res);

    header->addCheckable(i);

这很好用。在垂直和水平标题中绘制带有文本的复选框。 但这只有在我将此代码放入 MainWindow 构造函数时才有效。如果我将此代码用于例如按钮功能,这将不起作用。数据很好,但标题是不可见的。

ui->tableView->repaint();

不会工作。有人可能知道为什么会发生这种情况和/或如何解决这个问题的答案? 谢谢回答

【讨论】:

【参考方案2】:

Qt 模型不支持标题的项目标志。在用作标题的项目上设置项目标志无效。 QHeaderView 不支持绘制复选框。恐怕继承 QHeaderView 是最简单的方法。

我写了一个基于this FAQ page如何实现的示例。此类假定您使用 QStandardItemModel 并使用其标题项的标志。如果有人想使用其他模型类,则需要子类化 QAbstractItemModel 并实现缺少的接口并更改 headerview 实现。

class MyHeader : public QHeaderView

public:
  MyHeader(Qt::Orientation orientation, QWidget * parent = 0);

protected:
  QStandardItemModel* standard_model;
  virtual void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;
  virtual void mousePressEvent(QMouseEvent *event);
  virtual void setModel(QAbstractItemModel* model);

;

MyHeader::MyHeader(Qt::Orientation orientation, QWidget *parent) : QHeaderView(orientation, parent)

  standard_model = 0;


void MyHeader::paintSection(QPainter *painter, const QRect &rect, int logical_index) const 
  painter->save();
  QHeaderView::paintSection(painter, rect, logical_index);
  painter->restore();
  if (standard_model && orientation() == Qt::Horizontal) 
    QStandardItem* item = standard_model->horizontalHeaderItem(logical_index);
    if (item && item->isCheckable()) 
      int offset = (height() - style()->pixelMetric(QStyle::PM_IndicatorHeight))/2;
      int pos = sectionViewportPosition(logical_index);
      QStyleOptionButton option;
      option.rect = QRect(offset + pos, offset,
                          style()->pixelMetric(QStyle::PM_IndicatorWidth),
                          style()->pixelMetric(QStyle::PM_IndicatorHeight));
      if (item->checkState() == Qt::Checked) 
        option.state = QStyle::State_On;
       else 
        option.state = QStyle::State_Off;
      
      option.state |= QStyle::State_Enabled;
      style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter);
    
  


void MyHeader::mousePressEvent(QMouseEvent *event) 
  int offset = (height() - style()->pixelMetric(QStyle::PM_IndicatorHeight))/2;
  if (standard_model && orientation() == Qt::Horizontal) 
    for(int logical_index = 0; logical_index < count(); logical_index++) 
      int pos = sectionViewportPosition(logical_index);
      QRect rect(offset + pos, offset,
                 style()->pixelMetric(QStyle::PM_IndicatorWidth),
                 style()->pixelMetric(QStyle::PM_IndicatorHeight));
      if (rect.contains(event->pos())) 
        QStandardItem* item = standard_model->horizontalHeaderItem(logical_index);
        if (item && item->isCheckable()) 
          item->setCheckState(item->checkState() == Qt::Checked ? Qt::Unchecked : Qt::Checked);
          return;
        
      
    
  
  QHeaderView::mousePressEvent(event);


void MyHeader::setModel(QAbstractItemModel *model) 
  QHeaderView::setModel(model);
  standard_model = qobject_cast<QStandardItemModel*>(model);


//usage
QTableView  view;
QStandardItemModel model;
model.setColumnCount(5);
QStandardItem* item0 = new QStandardItem("some text");
item0->setCheckable(true);
item0->setCheckState(Qt::Checked);
item0->setText("some text");
model.setHorizontalHeaderItem(0, item0);
view.setModel(&model);
MyHeader *myHeader = new MyHeader(Qt::Horizontal, &view);
view.setHorizontalHeader(myHeader);
view.show();

【讨论】:

我正在为我的程序做另一件事,但我已经回到了这个问题。使用您的代码而不做任何更改后,标题是不可见的。

以上是关于带有小部件和文本的 QStandardItemModel 标头的主要内容,如果未能解决你的问题,请参考以下文章

将带有小部件和文本的行附加到 QStandardItemModel

带有刻度文本标签的 Qt 滑块小部件

是否有带有文本框和 2 个旋钮的默认 Android 视图小部件?

DataCell 溢出带有多个文本小部件的列 [dataTable]

Flutter 文本小部件

HTML 在 dojo 小部件中显示为纯文本