Как создать матрицу наподобие QWidget?

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


person Prinz Km    schedule 18.10.2019    source источник


Ответы (1)


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

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

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

ОБНОВЛЕНИЕ: предыдущая версия использовала фиктивный QTableWidgetItem для заполнения пустых областей, но я думаю, что это лучше, если вам все равно нужно использовать пользовательский виджет. Смотрите историю редактирования для предыдущей версии.

введите здесь описание изображения

// 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"
person Maxim Paperno    schedule 20.10.2019