Как создать QTableWidget с некоторыми ячейками, заполненными с использованием виджетов одинакового размера, и неиспользуемыми ячейками, заполненными размером виджетов? Результирующая таблица должна содержать строку/столбец как пустую, даже если виджет отсутствует.
Как создать матрицу наподобие QWidget?
Ответы (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"