Как создать Матрицу как QWidget? - PullRequest
0 голосов
/ 18 октября 2019

Как создать QTableWidget с несколькими ячейками, заполненными виджетами одинакового размера, и неиспользуемыми ячейками, заполненными размером виджетов? Результирующая таблица должна содержать пустую строку / столбец, даже если виджет отсутствует.

1 Ответ

1 голос
/ 20 октября 2019

Поскольку QTableWidget, по-видимому, должно содержать что-то в каждой ячейке, а по умолчанию используется редактируемое текстовое поле, кажется, что решением было бы вставить не редактируемый фиктивный элемент в пустые ячейки. Или иметь собственный виджет, который может скрывать его содержимое, что я и сделал в приведенном ниже примере.

Вы специально задали вопрос о фиксированном размере ... на самом деле есть несколько способов сделать это, в зависимости отна точных потребностях. Вы можете установить фиксированные размеры для всей таблицы, используя горизонтальные и вертикальные заголовки и делая их неизменяемыми. Другой способ - вызвать QTableView::setColumnWidth() / setRowHeight() для каждой строки / столбца (при добавлении / item или всякий раз).

Вот пример использования первого метода (установка размера в заголовках) и двух способов определения фактического размера. - либо фиксированный размер перед построением таблицы, либо использование поиска по элементу пользовательского виджета для определения размера.

ОБНОВЛЕНИЕ : предыдущая версия использовала пустышку 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"
...