提问人:Souleater 提问时间:7/26/2023 最后编辑:musicamanteSouleater 更新时间:7/31/2023 访问量:114
如何在QGroupBox,PyQt5中添加表
How to add a table in a QGroupBox, PyQt5
问:
我是 PyQt5 的新手,仍然很挣扎。我尝试了一整天在QGroupBox中添加行和列。我发现的唯一解决方案是添加一个 QTableWidget,问题在于小部件大小。
现在我只想拥有此表的标题,然后用户可以向此表添加行。 [ID、名称]
我想要细胞,但不是随之而来的“窗口”。如果我尝试将它对齐在QGroupBox的中心,它会将整个东西对齐在中心,而不是列。(列位于小部件的左上角,见图)
这是创建表的代码片段:
创建框
self.groupbox1 = QGroupBox('Data')
self.groupbox1.setMaximumWidth(350)
self.groupbox1.setMaximumHeight(400)
self.layout = QVBoxLayout()
self.groupbox1.setLayout(self.layout)
self.layout.addWidget(self.groupbox1)
创建一个 QTableWidget
self.table_widget = QTableWidget()
self.table_widget.setColumnCount(2)
self.table_widget.setHorizontalHeaderLabels(['ID', 'Data'])
self.table_widget.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
self.table_widget.resizeColumnsToContents()
self.table_widget.setMaximumSize(200, 200)
self.upper_layout.setAlignment(Qt.AlignCenter)
self.upper_layout.addWidget(self.table_widget)
我唯一发现的是 .resizeColumnsToContents 和 .setSectionResizeMode,它们只是根据其中的内容调整列。
通过设置表格小部件的最大大小,我使它变小了,但这不是我想要的。如果向表中添加了更多数据,则用户必须滚动,因为小部件不够大。 难道没有任何东西可以自动调整吗?
还是有其他解决方案?用户可以选择要显示的数据(将添加哪一行)的按钮应位于中心行的正下方,如果删除/添加行,则自动向上/向下移动。如果我必须有固定大小的 QTableWidget,这也是不可能的。
希望我解释得足够好。我感谢每一个能让我更接近解决方案的答案。:) (是的,我已经看过 Stack Overflow 上的所有相关帖子,可能每隔一页,不幸的是没有解决我的问题)
答:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QGroupBox, QVBoxLayout, QTableWidget, QPushButton, QTableWidgetItem, QHeaderView, QMessageBox
class TestApp(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle('Test Application')
self.setGeometry(200, 200, 400, 400)
# Create a QVBoxLayout for the main window
self.layout = QVBoxLayout(self) # 'self' refers to the main window
self.groupbox1 = QGroupBox('Data')
self.groupbox_layout = QVBoxLayout()
self.groupbox1.setLayout(self.groupbox_layout)
# Create a QTableWidget
self.table_widget = QTableWidget()
self.table_widget.setColumnCount(2)
self.table_widget.setHorizontalHeaderLabels(['ID', 'Name'])
self.table_widget.verticalHeader().setVisible(False)
self.table_widget.setShowGrid(False)
self.table_widget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# Create a QPushButton to add rows to the QTableWidget
self.add_row_button = QPushButton('Add Row')
self.add_row_button.clicked.connect(self.add_row)
# Add the QTableWidget and QPushButton to the QGroupBox layout
self.groupbox_layout.addWidget(self.table_widget)
self.groupbox_layout.addWidget(self.add_row_button)
# Add the QGroupBox to the main QVBoxLayout of the main window
self.layout.addWidget(self.groupbox1)
def add_row(self):
# Add a new row to the QTableWidget when the button is clicked
row_position = self.table_widget.rowCount()
self.table_widget.insertRow(row_position)
self.table_widget.setItem(
row_position, 0, QTableWidgetItem(str(row_position + 1)))
self.table_widget.setItem(row_position, 1, QTableWidgetItem(''))
if __name__ == '__main__':
app = QApplication(sys.argv)
window = TestApp()
window.show()
sys.exit(app.exec_())
尝试这个并使其适应您的项目。
这是输出:
版本 2023-07-26 第一个代码:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QGroupBox, QVBoxLayout, QTableWidget, QPushButton, QTableWidgetItem, QHeaderView, QMessageBox
class TestApp(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle('Test Application')
self.setGeometry(200, 200, 400, 400)
# Create a QVBoxLayout for the main window
self.layout = QVBoxLayout(self) # 'self' refers to the main window
self.groupbox1 = QGroupBox('Data')
self.groupbox_layout = QVBoxLayout()
self.groupbox1.setLayout(self.groupbox_layout)
# Create a QTableWidget
self.table_widget = QTableWidget()
self.table_widget.setColumnCount(2)
self.table_widget.setHorizontalHeaderLabels(['ID', 'Name'])
self.table_widget.verticalHeader().setVisible(False)
self.table_widget.setShowGrid(False)
# Set a fixed width for the 'ID' column
self.table_widget.setColumnWidth(0, 50)
#Set a fixed width for the 'NAME' column
self.table_widget.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
#Block widht fro the 'ID' column
self.table_widget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Fixed)
# Create a QPushButton to add rows to the QTableWidget
self.add_row_button = QPushButton('Add Row')
self.add_row_button.clicked.connect(self.add_row)
# Add the QTableWidget and QPushButton to the QGroupBox layout
self.groupbox_layout.addWidget(self.table_widget)
self.groupbox_layout.addWidget(self.add_row_button)
# Add the QGroupBox to the main QVBoxLayout of the main window
self.layout.addWidget(self.groupbox1)
def add_row(self):
# Add a new row to the QTableWidget when the button is clicked
row_position = self.table_widget.rowCount()
self.table_widget.insertRow(row_position)
self.table_widget.setItem(
row_position, 0, QTableWidgetItem(str(row_position + 1)))
self.table_widget.setItem(row_position, 1, QTableWidgetItem(''))
# Resize the 'Name' column to fit the contents
self.table_widget.resizeColumnToContents(1)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = TestApp()
window.show()
sys.exit(app.exec_())
试试这个,我已经调整了 ID 项链和 NAME 列的自动调整大小并阻止了它自动调整大小
这是输出:
版本 2023-07-26 第二个代码:
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QGroupBox, QVBoxLayout, QTableWidget, QPushButton, QTableWidgetItem, QHeaderView, QScrollArea, QSizePolicy
from PyQt5.QtCore import Qt
class TestApp(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle('Test Application')
self.setGeometry(200, 200, 400, 400)
# Create a QVBoxLayout for the main window
self.layout = QVBoxLayout(self) # 'self' refers to the main window
# Create a QScrollArea and set it as the main widget
self.scroll_area = QScrollArea(self)
self.layout.addWidget(self.scroll_area)
# Create a QWidget to hold the content
self.main_widget = QWidget()
self.main_layout = QVBoxLayout(self.main_widget)
# Create a QGroupBox to display the table
self.groupbox1 = QGroupBox('Data')
self.groupbox_layout = QVBoxLayout()
self.groupbox1.setLayout(self.groupbox_layout)
self.groupbox1.setWindowFlag(Qt.WindowContextHelpButtonHint, False)
self.groupbox1.hide() # Hide the group box initially
# Create a QTableWidget
self.table_widget = QTableWidget()
self.table_widget.setColumnCount(2)
self.table_widget.setHorizontalHeaderLabels(['ID', 'Name'])
self.table_widget.verticalHeader().setVisible(False)
self.table_widget.setShowGrid(False)
self.table_widget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# Add the QTableWidget to the QGroupBox layout
self.groupbox_layout.addWidget(self.table_widget)
# Add the QGroupBox to the main_layout of the main_widget
self.main_layout.addWidget(self.groupbox1)
# Create a QPushButton to add rows to the QTableWidget
self.add_row_button = QPushButton('Add Row')
self.add_row_button.clicked.connect(self.add_row)
# Add the QPushButton to the main_layout of the main_widget
self.main_layout.addWidget(self.add_row_button)
# Set the main_widget as the widget for the QScrollArea
self.scroll_area.setWidget(self.main_widget)
# Set the QScrollArea to expand the widget vertically
self.scroll_area.setWidgetResizable(True)
self.main_widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum)
# Set the number of rows to display (2 rows in this case)
self.displayed_rows = 1
# Calculate and set the initial height of the QScrollArea based on the QTableWidget height
table_height = self.table_widget.rowHeight(0) * self.displayed_rows + self.groupbox_layout.spacing()
self.scroll_area.setMinimumHeight(table_height)
# Set the maximum height for the QGroupBox
self.groupbox1.setMaximumHeight(table_height)
def add_row(self):
if not self.groupbox1.isVisible(): # Show the group box when the first row is added
self.groupbox1.show()
# Add a new row to the QTableWidget when the button is clicked
row_position = self.table_widget.rowCount()
self.table_widget.insertRow(row_position)
self.table_widget.setItem(row_position, 0, QTableWidgetItem(str(row_position + 1)))
self.table_widget.setItem(row_position, 1, QTableWidgetItem(''))
# Recalculate the new height of the QGroupBox based on the updated QTableWidget height
table_height = self.table_widget.rowHeight(
0) * (self.displayed_rows + 1.5) + self.groupbox_layout.spacing()
self.groupbox1.setFixedHeight(table_height)
self.table_widget.setMinimumHeight(table_height)
if (self.displayed_rows < 5):
self.displayed_rows += 1
else:
# Enable scrolling when the displayed rows reach 5
self.update_scroll_area_height()
def update_scroll_area_height(self):
table_height = self.table_widget.rowHeight(
0) * (self.displayed_rows + 2) + self.groupbox_layout.spacing()
self.groupbox1.setFixedHeight(table_height)
self.scroll_area.setMinimumHeight(table_height)
# Enable vertical scrolling
self.scroll_area.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = TestApp()
window.show()
sys.exit(app.exec_())
尝试这个并使其适应您的项目。
评论
这是Francesca Mazzeo答案的修改版本。
它使用具有重新实现方法的子类来获取“随着添加的行而增长”行为。QTableWidget
resizeEvent()
有一件奇怪的事情我不明白:添加第一行不会触发。后续行会这样做。resizeEvent()
我以任何方式发布此内容,希望有人知道如何解决这个问题。
import sys
from PyQt5.QtWidgets import QApplication, QWidget, QGroupBox, QVBoxLayout, QTableWidget, QPushButton, QTableWidgetItem, QHeaderView, QMessageBox
# class ExpandingTableWidget(QTableWidget):
# def resizeEvent(self, event):
# super().resizeEvent(event)
# height = self.horizontalHeader().height()
# row_count = self.verticalHeader().count()
# for i in range(row_count):
# height += self.verticalHeader().sectionSize(i)
#
# self.setMaximumHeight(height + 2)
class TestApp(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle('Test Application')
self.setGeometry(200, 200, 400, 400)
# Create a QVBoxLayout for the main window
self.layout = QVBoxLayout(self) # 'self' refers to the main window
self.groupbox1 = QGroupBox('Data')
self.groupbox_layout = QVBoxLayout()
self.groupbox1.setLayout(self.groupbox_layout)
# Create a QTableWidget
self.table_widget = ExpandingTableWidget()
self.table_widget.setColumnCount(2)
self.table_widget.setHorizontalHeaderLabels(['ID', 'Name'])
self.table_widget.verticalHeader().setVisible(False)
self.table_widget.setShowGrid(False)
self.table_widget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# Create a QPushButton to add rows to the QTableWidget
self.add_row_button = QPushButton('Add Row')
self.add_row_button.clicked.connect(self.add_row)
# Add the QTableWidget and QPushButton to the QGroupBox layout
self.groupbox_layout.addWidget(self.table_widget, stretch=1)
self.groupbox_layout.addStretch(0)
self.groupbox_layout.addWidget(self.add_row_button)
# Add the QGroupBox to the main QVBoxLayout of the main window
self.layout.addWidget(self.groupbox1)
def add_row(self):
# Add a new row to the QTableWidget when the button is clicked
row_position = self.table_widget.rowCount()
self.table_widget.insertRow(row_position)
self.table_widget.setItem(
row_position, 0, QTableWidgetItem(str(row_position + 1)))
self.table_widget.setItem(row_position, 1, QTableWidgetItem(''))
if __name__ == '__main__':
app = QApplication(sys.argv)
window = TestApp()
window.show()
sys.exit(app.exec())
编辑:
使用 musicamente 的评论的新 QTablewidget 子类:
class ExpandingTableWidget(QTableWidget):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.model().rowsInserted.connect(self.set_height)
self.model().columnsInserted.connect(self.set_height)
def set_height(self):
height = self.horizontalHeader().height() + self.verticalHeader().length() + self.frameWidth() * 2
self.setMaximumHeight(height)
评论
rowsInserted
columnsInserted
length()
frameWidth()
评论