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

时间:2013-12-26 22:32:22

标签: qt qtgui qstandarditemmodel qcheckbox

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

enter image description here

在QStanndardItemModel的标题中。我试过这个

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的类,但我不知道这是否有助于解决我的问题。我会问是否有一个简单的方法来实现这一目标?

此致

2 个答案:

答案 0 :(得分:0)

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();

答案 1 :(得分:0)


我做了这样的事情:

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();

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