如何创建像QWidget这样的矩阵?

时间:2019-10-18 17:04:21

标签: qt qtablewidget

如何创建一个QTableWidget,其某些单元格使用大小统一的小部件填充,未使用的单元格中填充小部件的大小?即使没有小部件,生成的表也应包含一行/列为空白。

1 个答案:

答案 0 :(得分:1)

由于QTableWidget显然必须在每个单元格中包含某些内容,并且默认值是可编辑的文本框,因此看来解决方案是将不可编辑的虚拟项插入空白单元格。或者有一个可以隐藏其内容的自定义小部件,这就是我在下面的示例中所做的。

您具体询问了固定大小...确实有很多方法可以解决,具体取决于确切的需求。您可以通过使用水平和垂直标题并使它们不可调整大小来在整个表上设置固定大小。另一种方法是为每个行/列调用QTableView::setColumnWidth() / setRowHeight()(在添加/项目时或在任何时候)。

这是一个使用前一种方法的示例(在标题上设置大小),以及两种确定实际大小的方法-构建表之前的固定大小,或在自定义小部件项目上使用查找来确定大小。

UPDATE :先前版本使用虚拟QTableWidgetItem来填充空白区域,但是我认为如果仍然需要使用自定义窗口小部件,这会更好。查看以前版本的编辑历史记录。

enter image description here

// main.cpp
#include <QtWidgets>

// A custom table widget item which contains a progress bar. The bar is
//   hidden if the value is set to < 0.
class ProgressBarTwItem : public QWidget, public QTableWidgetItem
{
    Q_OBJECT
  public:
    ProgressBarTwItem(QWidget *parent = nullptr, int value = -1) :
      QWidget(parent),
      QTableWidgetItem(QTableWidgetItem::UserType)
    {
      QHBoxLayout *l = new QHBoxLayout(this);
      l->setContentsMargins(0,0,0,0);
      m_pb = new QProgressBar(this);
      // don't let PB size dictate our size
      m_pb->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
      m_pb->setAlignment(Qt::AlignCenter);
      m_pb->setMaximum(44);
      l->addWidget(m_pb);
      setValue(value);
    }

    QSize sizeHint() const override { return QSize(75, 25); }

  public slots:
    void setValue(int value = -1) const
    {
      m_pb->setVisible(value > -1);
      if (value > -1)
        m_pb->setValue(value);
    }

  private:
    QProgressBar *m_pb;
};

int main(int argc, char *argv[])
{
  QApplication a(argc, argv);
  a.setStyle("Fusion");

  QDialog d;
  d.setLayout(new QVBoxLayout);
  QTableWidget *tw = new QTableWidget(5, 4, &d);
  d.layout()->addWidget(tw);

  // set to `true` to find the largest size from added custom widgets,
  //  otherwise use preset size
  const bool useWidgetSize = true;

  // This will be the fixed cell size, either preset or determined from custom widget.
  // If looking up from widgets, this becomes the minimum size 
  //   (eg. in case widgets didn't return valid sizes).
  QSize cellSize = (useWidgetSize ? QSize(10, 10) : QSize(50, 15));

  for (int r=0; r < tw->rowCount(); ++r) {
    for (int c=0; c < tw->columnCount(); ++c) {
      // make some widgets hidden and others display a progress value
      const int val = (!((r*c) % (1+c)) ? -1 : (c+1 + r*10));
      ProgressBarTwItem *item = new ProgressBarTwItem(tw, val);
      tw->setCellWidget(r, c, item);
      // tw->setItem(r, c, item);  // needed? widget is shown anyway... docs not clear.
      // Check the size.
      if (useWidgetSize)
        cellSize = cellSize.expandedTo(item->sizeHint());
    }
  }

  // set fixed sizes for columns and rows on the horizontal and vertical headers
  //  respectively (this works even if they are hidden)
  tw->horizontalHeader()->setDefaultSectionSize(cellSize.width());
  tw->horizontalHeader()->setSectionResizeMode(QHeaderView::Fixed);
  tw->verticalHeader()->setDefaultSectionSize(cellSize.height());
  tw->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);

  return d.exec();
}

#include "main.moc"