【发布时间】:2020-09-26 08:44:54
【问题描述】:
我正在尝试实现一个类似于以下的pyqt5表:
首先:我什至不确定 QTableWidget 是不是最合适的小部件,因为我对 Qt 没有太多经验。 QGridLayout 可能更适合。我先尝试过,但不知如何使其符合要求,任何建议都将不胜感激。
表格要求是:
- 一些单元格包含文本、一些 QCheckBoxes 和一些 QRadioButtons
- 在调整大小时,表格宽度必须始终填充其父级宽度的 100%(我目前使用的是
setSectionResizeMode(QHeaderView.Stretch)) - 表格应该可以垂直滚动
- 它的一些列有不同的相对宽度,必须保持这种关系(这里开始我的问题)
- 每个列的居中都不相同(在文档中找不到如何实现这一点)
我目前的问题是setSectionResizeMode 的使用与resizeSection 冲突。我可以有不同的列宽或可拉伸的表格宽度,但我不知道如何同时实现。
示例代码如下所示:
from PyQt5.QtWidgets import QApplication, QWidget, QHeaderView, QTableWidget, QTableWidgetItem, QVBoxLayout
import sys
data = {'col1':['1','2','3','4'],
'col2':['1','2','1','3'],
'col3':['1','1','2','1']}
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.table = QTableWidget()
self.table.setRowCount(4)
self.table.setColumnCount(3)
self.table.verticalHeader().hide()
self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# self.table.horizontalHeader().resizeSection(1, 200) <-- no effect if stretch is activated
self.table.setHorizontalHeaderLabels([colName for colName in data])
self.fillTable()
self.layout = QVBoxLayout()
self.layout.addWidget(self.table)
self.setLayout(self.layout)
def fillTable(self):
for colNumber, colName in enumerate(data):
for rowNumber, value in enumerate(data[colName]):
self.table.setItem(rowNumber, colNumber, QTableWidgetItem(value))
if __name__=="__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
app.exec_()
这是我的另一个尝试,使用 QGridLayout。这里的问题是调整窗口大小时列不展开。
import sys
from PyQt5.QtWidgets import (QWidget, QGridLayout, QLabel, QPushButton, QApplication, QScrollArea, QVBoxLayout)
from PyQt5.QtCore import Qt
class MainWindow(QWidget):
def __init__(self):
super().__init__()
# Label
self.label = QLabel('Test')
# Grid
self.grid = QWidget()
self.gridLayout = QGridLayout()
self.grid.setLayout(self.gridLayout)
self.grid.setMinimumWidth(600) # Without this, the width relations are not kept
# Grid elements
for i in range(20):
self.gridLayout.addWidget(QPushButton('A'), i, 0, 1, 1)
self.gridLayout.addWidget(QPushButton('B'), i, 1, 1, 3)
self.gridLayout.addWidget(QPushButton('C'), i, 4, 1, 1)
# Scroll area
self.scrollArea = QScrollArea()
self.scrollArea.setWidget(self.grid)
self.scrollArea.setMinimumWidth(self.grid.sizeHint().width())
self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
# Window layout
self.layout = QVBoxLayout()
self.layout.addWidget(self.label)
self.layout.addWidget(self.scrollArea)
self.setLayout(self.layout)
if __name__ == '__main__':
app = QApplication(sys.argv)
windowExample = MainWindow()
windowExample.show()
sys.exit(app.exec_())
【问题讨论】:
-
你确定你真的需要一张桌子吗?如果您不需要项目视图的功能,但只想要一种将标签和复选框/单选框对齐的方法,那么您不能在 QScrollArea 内使用带有 QGridLayout 集的普通 QWidget 吗? (顺便说一句,自 Qt4 以来,QGridView 不再存在)。列是否可以调整大小?表可以调整大小吗? “项目”是否应该始终占据整个可用空间?您是否考虑过为单个列使用
setSectionResizeMode,而不是为所有列设置它? -
@musicamante 好的,这是一个错字(我指的是 QGridLayout,而不是 QGridView)。 GridLayout 是我的第一次尝试(找到在我的问题的新版本中添加的示例),但是当窗口大小发生变化时,我无法调整列的大小。是的,列应该可以调整大小,并且网格或表格应该占据所有宽度。
-
我建议您编辑您的帖子并提供您对 QGridLayout 的尝试,因为它可能是更实际的选择。
-
@musicamante 这就是我刚刚所做的。
-
对不起,我没有得到编辑。我刚刚使用网格布局方法发布了一个答案。
标签: python pyqt pyqt5 qtablewidget