PySide - PyQt: Как сделать так, чтобы ширина столбца QTableWidget задавалась как пропорция доступного пространства?
Я разрабатываю компьютерное приложение с помощью PySide и использую QTableWidget. Допустим, в моей таблице 3 столбца, но содержащиеся в них данные сильно отличаются, например (для каждой строки) длинное предложение в первом столбце, а затем 3-значные числа в двух последних столбцах. Я хотел бы изменить размер моей таблицы, чтобы настроить ее размер в соответствии с данными, или, по крайней мере, иметь возможность устанавливать размеры столбцов как (скажем) 70/15/15 % доступного пространства.
Каков наилучший способ сделать это?
я пробовал table.horizontalHeader().setResizeMode(QHeaderView.Stretch)
после прочтения этого вопроса, но он составляет 3 столбца одинакового размера.
Я также пытался table.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
благодаря комментарию Fabio, но он не заполняет все доступное пространство по мере необходимости.
ни Interactive
, Fixed
, Stretch
, ResizeToContents
из документации QHeaderView, кажется, дает мне то, что мне нужно (см. второе редактирование).
Буду признателен за любую помощь, даже если она для Qt / C++! Большое спасибо.
РЕДАКТИРОВАТЬ: Я нашел своего рода обходной путь, но это все еще не то, что я ищу:
header = table.horizontalHeader()
header.setResizeMode(QHeaderView.ResizeToContents)
header.setStretchLastSection(True)
Было бы лучше, если бы существовал setStretchFirstSection
метод, но, к сожалению, кажется, не один.
РЕДАКТИРОВАТЬ 2:
Единственное, что можно изменить в таблице - это последний столбец, пользователь может ввести в него число. Красные стрелки показывают, что я хотел бы иметь.
11 ответов
Это можно решить, установив режим изменения размера для каждого столбца. Первый раздел должен растягиваться, чтобы занимать доступное пространство, в то время как последние два раздела просто изменяют размер своего содержимого:
PyQt4:
header = self.table.horizontalHeader()
header.setResizeMode(0, QtGui.QHeaderView.Stretch)
header.setResizeMode(1, QtGui.QHeaderView.ResizeToContents)
header.setResizeMode(2, QtGui.QHeaderView.ResizeToContents)
PyQt5:
header = self.table.horizontalHeader()
header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
Как упоминалось ранее, вы можете сделать это, установив режим изменения размера каждого столбца. Однако, если у вас много столбцов, это может быть много кода. Я делаю это, устанавливая "общий" режим изменения размера на "ResizeToContent", а затем для одного (или нескольких) столбцов "растягивать"!
Вот код:
PyQt4:
header = self.table.horizontalHeader()
header.setResizeMode(QtGui.QHeaderView.ResizeToContents)
header.setResizeMode(0, QtGui.QHeaderView.Stretch)
PyQt5:
header = self.table.horizontalHeader()
header.setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
PyQt4
header = self.table.horizontalHeader()
header.setResizeMode(0, QtGui.QHeaderView.Stretch)
header.setResizeMode(1, QtGui.QHeaderView.ResizeToContents)
header.setResizeMode(2, QtGui.QHeaderView.ResizeToContents)
header.setResizeMode(3, QtGui.QHeaderView.Stretch)
PyQt5
header = self.table.horizontalHeader()
header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeToContents)
header.setSectionResizeMode(3, QtWidgets.QHeaderView.Stretch)
Я использовал это, и setMinumsectionsize решил мою проблему размера ячейки Qtableview
self.questionWidget.tableView.setModel(self.model)
self.questionWidget.tableView.verticalHeader().setVisible(False)
self.questionWidget.tableView.horizontalHeader().setMinimumSectionSize(200)
Вы можете сделать это с QItemDelegates
или же QStyledItemDelegates
, Если вы хотите изменить размер содержимого и иметь автоматическое растяжение, вам нужно выбрать, какой столбец является столбцом растягивания.
class ResizeDelegate(QStyledItemDelegate):
def __init__(self, table, stretch_column, *args, **kwargs):
super(ResizeDelegate, self).__init__(*args, **kwargs)
self.table = table
self.stretch_column = stretch_column
def sizeHint(self, option, index):
size = super(ResizeDelegate, self).sizeHint(option, index)
if index.column() == self.stretch_column:
total_width = self.table.viewport().size().width()
calc_width = size.width()
for i in range(self.table.columnCount()):
if i != index.column():
option_ = QtGui.QStyleOptionViewItem()
index_ = self.table.model().index(index.row(), i)
self.initStyleOption(option_, index_)
size_ = self.sizeHint(option_, index_)
calc_width += size_.width()
if calc_width < total_width:
size.setWidth(size.width() + total_width - calc_width)
return size
...
table = QTableWidget()
delegate = ResizeDelegate(table, 0)
table.setItemDelegate(delegate)
... # Add items to table
table.resizeColumnsToContents()
Вы можете установить режим изменения размера на ResizeToContents
или, если вы хотите, чтобы пользователь мог регулировать ширину столбца по мере необходимости, просто вызовите resizeColumnsToContents
вручную после внесения изменений в элементы таблицы.
Вам также может понадобиться немного поработать с вычислениями ширины из-за полей и отступов между столбцами (например, добавить один или два пикселя к calculated_width
для каждого столбца для учета границы ячейки).
Мне пришлось удалить QtWidget, чтобы мой работал.
header = self.tag_table.horizontalHeader()
header.setSectionResizeMode(QHeaderView.ResizeToContents)
PyQt6
header = self.table.horizontalHeader()
header.setSectionResizeMode(0, QtWidgets.QHeaderView.ResizeMode.Stretch)
header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeMode.ResizeToContents)
header.setSectionResizeMode(2, QtWidgets.QHeaderView.ResizeMode.ResizeToContents)
Параметры изменения размера являются перечислениями типаResizeMode
Другие доступные варианты:
Interactive = ... # type: QHeaderView.ResizeMode
Fixed = ... # type: QHeaderView.ResizeMode
Stretch = ... # type: QHeaderView.ResizeMode
ResizeToContents = ... # type: QHeaderView.ResizeMode
Custom = ... # type: QHeaderView.ResizeMode
до этого исправления в PySide6 5 столбцов в QTableView выходили за пределы видимой таблицы.
после этого исправления они идеально выровнены (кстати, табличное представление имеет фиксированную ширину 371 пиксель) (также с использованием QtDesigner)
self.table_view = QTableView()
self.model.setHeaderData(index,Qt.Horizontal,value)
self.table_view.setColumnWidth(0,65) #(index,width-px)
self.table_view.setColumnWidth(1,75)
self.table_view.setColumnWidth(2,75)
self.table_view.setColumnWidth(3,75)
self.table_view.setColumnWidth(4,71)
Мне не удалось найти «стандартное» решение, но я сделал следующее:
Создайте поток, который проверяет, изменился ли размер таблицы каждые 50 миллисекунд, и если это так, инициируйте сигнал в слот, который обновляет ширину столбцов на основе текущего размера таблицы.
В приведенном ниже примере соотношение ширины столбцов составляет 1:1:2.
Пример:
import time
from PySide6.QtCore import Signal
# Class definition here
def __init__(self):
# Class initialization here
self.signal_table_size_changed = Signal()
self.signal_table_size_changed.connect(self.adjust_table_column_width)
self.table_width = None
threading.Thread(target=self.table_size_watcher).start()
def adjust_table_column_width(self):
self.table_width = self.table.size().width()
self.table.setColumnWidth(0, 0.25 * self.table_width)
self.table.setColumnWidth(1, 0.25 * self.table_width)
self.table.setColumnWidth(2, 0.50 * self.table_width)
def table_size_watcher(self):
while True:
if self.table_width != self.table.size().width():
self.signal_table_size_changed.emit()
time.sleep(0.05)
Это сработало для меня в PyQt5:
table_name.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
Он автоматически отрегулирует размер всех столбцов.
Вот все мои настройки горизонтального заголовка:
table_name.horizontalHeader().setVisible(True)
table_name.horizontalHeader().setCascadingSectionResizes(True)
table_name.horizontalHeader().setDefaultSectionSize(140)
table_name.horizontalHeader().setHighlightSections(False)
table_name.horizontalHeader().setMinimumSectionSize(100)
table_name.horizontalHeader().setSortIndicatorShown(False)
table_name.horizontalHeader().setStretchLastSection(False)
table_name.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
В классе, который наследуется от QTableWidget, я реализовал эту функцию в PyQt5:
def set_header_stretch_first_section(self):
header = self.horizontalHeader()
header.setSectionResizeMode(0, QHeaderView.Stretch)
for i in range(1, self.columnCount()):
header.setSectionResizeMode(i, QHeaderView.ResizeToContents)