如何在 QGroupBox、PyQt5 中添加表格

问题描述 投票:0回答:3

我对 PyQt5 还很陌生,但仍然很挣扎。我一整天都尝试在 QGroupBox 中添加行和列。我发现的唯一解决方案是添加 QTableWidget,问题是小部件的大小。

现在我只想拥有该表的标题,然后用户可以向该表添加行。 [ID、姓名]

我想要细胞,但不想要它附带的“窗口”。如果我尝试将它对齐在 QGroupBox 的中心,它会将整个东西对齐在中心,而不是列。 (这些列位于小部件的左上角,参见图片)

How it currently looks

这是创建表的代码片段:

创建盒子

    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 上的所有相关帖子,可能还有其他所有页面,不幸的是没有解决我的问题)

python-3.x pyqt5 qtablewidget qgroupbox
3个回答
0
投票

这是 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)

0
投票

这是我到目前为止所拥有的:

# Create the box
self.groupbox1 = QGroupBox('Data')
self.groupbox1.setMaximumWidth(350)
self.groupbox1.setMaximumHeight(400)
self.layout = QVBoxLayout()
self.groupbox1.setLayout(self.layout)
self.upper_layout.addWidget(self.groupbox1)

# 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.setMaximumWidth(250)
self.table_widget.resizeColumnsToContents()

self.table_widget.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
    self.layout.setAlignment(Qt.AlignCenter)

self.layout.addWidget(self.table_widget, stretch=1)

# Add the '+' button to 'Selected Data' box
add_row_button = QPushButton("+")
add_row_button.setFixedSize(30, 28)
add_row_button.clicked.connect(self.add_row)
self.layout.addWidget(add_row_button, alignment=Qt.AlignCenter)

self.layout.addStretch(0)

def add_row(self):
# can't open more than 5 rows
if self.table_widget.rowCount() == 5:
    return
# Add a new row to the QTableWidget when the button is clicked
row_position = self.table_widget.rowCount()
self.table_widget.insertRow(row_position)

看起来像这样: pic

我使用了之前答案中的 ExpandingTableWidget() 的编辑。 @mahkitah

正如我之前在评论部分问过的:

是否有可能将ID列变小而名称变大?也许使用 self.table_widget.resizeColumnsToContents() 或 ExpandingTableWidget 类中的 set_width 方法?

很抱歉再次询问,但认为查看代码和输出更容易,所以我创建了一个新答案。 :)


0
投票

嗨,我读了你的问题,我想帮助你......

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_())

尝试一下并使其适应您的项目。我希望这有帮助,如果没有,请重复这个问题。

这是输出👇👇

编码快乐!🚀

© www.soinside.com 2019 - 2024. All rights reserved.