PyQt5. Растягивание таблицы QTableWidget() на всю область
Есть таблица QTableWidget() со свойством table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) для растягивания столбцов на всю областью. Однако при использовании этого свойства теряется возможность изменения ширины столбцов в окне. Можно ли как-то изменить это поведение? Методы setStretchLastSection(True) и setSectionResizeMode(index, QHeaderView.Stretch) не подходят, так как количество столбцов определятся динамически при заполнении таблицы, в этом случае таблица может уйти за границы поля либо будет большой перекос по ширине в каком-то одном выбранном столбце, этого хотелось бы избежать.
import sys
from PyQt5.QtWidgets import *
class MainInterface(QMainWindow):
def __init__(self, tuple_of_dict: tuple = None):
super().__init__()
self.__tuple_of_dict = tuple_of_dict
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.setMinimumHeight(400)
self.setMinimumWidth(650)
table = QTableWidget()
if self.__tuple_of_dict:
table_headers = tuple(self.__tuple_of_dict[0].keys())
table.setColumnCount(len(table_headers))
table.setRowCount(len(self.__tuple_of_dict))
table.setHorizontalHeaderLabels(table_headers)
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# table.horizontalHeader().setStretchLastSection(True)
# table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
for num, row in enumerate(self.__tuple_of_dict):
for column in table_headers:
if isinstance(row[column], bool):
row[column] = "True" if row[column] else "False"
elif isinstance(row[column], type(None)):
row[column] = "None"
row_item = QTableWidgetItem(row[column])
table.setItem(num, table_headers.index(column), row_item)
row_item.setToolTip(row[column])
box = QGroupBox("Table")
h_layout = QHBoxLayout(box)
h_layout.addWidget(table)
g_layout = QGridLayout(self.centralWidget)
g_layout.addWidget(box, 1, 1)
if __name__ == '__main__':
result = ({"id": "673543", "devicename": "bla_bla_bla", "description": "My Fancy Device"}, )
app = QApplication(sys.argv)
# app.setStyleSheet(MAIN_QSS)
app.setStyle("Fusion")
ex = MainInterface(tuple_of_dict=result)
ex.show()
sys.exit(app.exec_())
Ответы (2 шт):
Вы можете указать какой столбец будет растягиваться (не все сразу, как в вашем примере!), при этом все размеры будут меняться
import sys
from PyQt5.QtWidgets import *
class MainInterface(QMainWindow):
def __init__(self, tuple_of_dict: tuple = None):
super().__init__()
self.__tuple_of_dict = tuple_of_dict
self.centralWidget = QWidget()
self.setCentralWidget(self.centralWidget)
self.setMinimumHeight(400)
self.setMinimumWidth(650)
table = QTableWidget()
if self.__tuple_of_dict:
table_headers = tuple(self.__tuple_of_dict[0].keys())
table.setColumnCount(len(table_headers))
table.setRowCount(len(self.__tuple_of_dict))
table.setHorizontalHeaderLabels(table_headers)
for num, row in enumerate(self.__tuple_of_dict):
for column in table_headers:
if isinstance(row[column], bool):
row[column] = "True" if row[column] else "False"
elif isinstance(row[column], type(None)):
row[column] = "None"
row_item = QTableWidgetItem(row[column])
table.setItem(num, table_headers.index(column), row_item)
row_item.setToolTip(row[column])
table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) # вот так
box = QGroupBox("Table")
h_layout = QHBoxLayout(box)
h_layout.addWidget(table)
g_layout = QGridLayout(self.centralWidget)
g_layout.addWidget(box, 1, 1)
if __name__ == '__main__':
result = ({"id": "673543", "devicename": "bla_bla_bla", "description": "My Fancy Device", "another": "value"}, )
app = QApplication(sys.argv)
app.setStyle("Fusion")
ex = MainInterface(tuple_of_dict=result)
ex.show()
sys.exit(app.exec_())
Нашел для вас пример. Из минусов - "руками" можно оставить пустое место после последней секции
import sys
from PyQt5 import QtWidgets
from PyQt5.QtCore import QAbstractTableModel, Qt, QVariant
class TableModel(QAbstractTableModel):
def __init__(self, parent, datain, headerdata):
QAbstractTableModel.__init__(self, parent)
self.arraydata=datain
self.headerdata=headerdata
def rowCount(self,p):
return len(self.arraydata)
def columnCount(self,p):
if len(self.arraydata)>0:
return len(self.arraydata[0])
return 0
def data(self, index, role):
if not index.isValid():
return QVariant()
elif role != Qt.DisplayRole:
return QVariant()
return QVariant(self.arraydata[index.row()][index.column()])
def headerData(self, col, orientation, role):
if orientation==Qt.Horizontal and role==Qt.DisplayRole:
return self.headerdata[col]
return None
class MyHeaderView(QtWidgets.QHeaderView):
def __init__(self,parent):
QtWidgets.QHeaderView.__init__(self,Qt.Horizontal,parent)
self.sectionResized.connect(self.myresize)
def myresize(self, *args):
'''Resize while keep total width constant'''
# keep a copy of column widths
ws=[]
for c in range(self.count()):
wii=self.sectionSize(c)
ws.append(wii)
if args[0]>0 or args[0]<self.count():
for ii in range(args[0],self.count()):
if ii==args[0]:
# resize present column
self.resizeSection(ii,args[2])
elif ii==args[0]+1:
# if present column expands, shrink the one to the right
self.resizeSection(ii,ws[ii]-(args[2]-args[1]))
else:
# keep all others as they were
self.resizeSection(ii,ws[ii])
def resizeEvent(self, event):
"""Resize table as a whole, need this to enable resizing"""
super(QtWidgets.QHeaderView, self).resizeEvent(event)
self.setSectionResizeMode(1,QtWidgets.QHeaderView.Stretch)
for column in range(self.count()):
self.setSectionResizeMode(column, QtWidgets.QHeaderView.Stretch)
width = self.sectionSize(column)
self.setSectionResizeMode(column, QtWidgets.QHeaderView.Interactive)
self.resizeSection(column, width)
return
class MainFrame(QtWidgets.QMainWindow):
def __init__(self):
super(MainFrame,self).__init__()
self.centralWidget = QtWidgets.QWidget()
self.setCentralWidget(self.centralWidget)
self.setMinimumHeight(400)
self.setMinimumWidth(650)
self.doc_table = self.createTable()
box = QtWidgets.QGroupBox("Table")
h_layout = QtWidgets.QHBoxLayout(box)
h_layout.addWidget(self.doc_table)
g_layout = QtWidgets.QGridLayout(self.centralWidget)
g_layout.addWidget(box, 1, 1)
self.show()
def createTable(self):
# create some dummy data
self.tabledata=[['aaa' ,' title1', True, 1999],
['bbb' ,' title2', True, 2000],
['ccc' ,' title3', False, 2001]
]
header=['author', 'title', 'read', 'year']
tablemodel=TableModel(self,self.tabledata,header)
tv=QtWidgets.QTableView(self)
hh=MyHeaderView(self)
tv.setHorizontalHeader(hh)
tv.setModel(tablemodel)
tv.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
tv.setShowGrid(True)
hh.setSectionsMovable(True)
hh.setStretchLastSection(False)
return tv
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super(MainWindow,self).__init__()
self.main_frame=MainFrame()
self.setCentralWidget(self.main_frame)
self.setGeometry(100,100,800,600)
self.show()
if __name__=='__main__':
app=QtWidgets.QApplication(sys.argv)
mainwindow=MainWindow()
sys.exit(app.exec_())
P.S.: Мопед не мой я просто загуглил объяву(ц)