Как изменить размер QMainWindow, чтобы он соответствовал QTableWidget, у которого есть setVerticalHeaderLabels

Вот пример кода:

      from PyQt5.QtWidgets import QApplication, QTableWidget, QTableWidgetItem, \
    QMainWindow
from PyQt5.QtCore import QSize
import sys

DATA = {
    f'col{i}': [f'{i * j}' for j in range(1, 10)] for i in range(1, 10)
}


class Table(QTableWidget):
    def __init__(self, d):
        m = len(d[next(iter(d))])
        n = len(DATA)
        super().__init__(m, n)

        hor_headers = []
        for n, (key, values) in enumerate(DATA.items()):
            hor_headers.append(key)
            for m, item in enumerate(values):
                qtitem = QTableWidgetItem(item)
                self.setItem(m, n, qtitem)
        self.setHorizontalHeaderLabels(hor_headers)
        # the sizeHint works fine if I disable this line
        self.setVerticalHeaderLabels(f'row{i}' for i in range(1, m + 2))

        self.resizeColumnsToContents()
        self.resizeRowsToContents()

    # improves the situation but still the window is smaller than the table
    def sizeHint(self):
        hh = self.horizontalHeader()
        vh = self.verticalHeader()
        fw = self.frameWidth() * 2
        return QSize(
            hh.length() + vh.width() + fw,
            vh.length() + hh.height() + fw)


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('<TITLE>')
        table = Table(DATA)
        self.setCentralWidget(table)
        # did not work
        # self.setFixedSize(self.layout().sizeHint())


def main(args):
    app = QApplication(args)
    main_win = MainWindow()
    main_win.show()
    raise SystemExit(app.exec_())


if __name__ == "__main__":
    main(sys.argv)

Вот результат:

9-я строка и 9-й столбец не отображаются, есть полосы прокрутки.

Если я закомментирую self.setVerticalHeaderLabels(f'row{i}' for i in range(1, m + 2)) строка, тогда он будет работать:

Как я могу идеально подогнать главное окно под виджет таблицы, имея вертикальные метки заголовков?

As you can see in code comments, I have tried the solutions suggested at python qt : automatically resizing main window to fit content but they are not are not working.

1 ответ

Решение

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

Это означает, что до этого момента размер каждого заголовка зависит от его основного содержимого по умолчанию (номера строки для вертикального заголовка).

Решение простое: используйте не размер заголовка, а их подсказки, которые вычисляются с использованием фактического текста, который будет отображаться:

      def sizeHint(self):
    hh = self.horizontalHeader()
    vh = self.verticalHeader()
    fw = self.frameWidth() * 2
    return QSize(
        hh.length() + vh.sizeHint().width() + fw,
        vh.length() + hh.sizeHint().height() + fw)
Другие вопросы по тегам