如何通过单击 QPushButton 打印 QTableWidget

Posted

技术标签:

【中文标题】如何通过单击 QPushButton 打印 QTableWidget【英文标题】:How can I print a QTableWidget by clicking on QPushButton 【发布时间】:2020-08-12 12:16:01 【问题描述】:

我有一个带有两个选项卡的界面:在第一个选项卡中,我要求用户输入参数,在第二个选项卡中,我想打印以下 QTableWidget。

所以基本上在第一个选项卡上我有一个 QPushButton,我称之为进程,通常,当我按下它时,我想将信息发送到第二个选项卡。

现在我只是尝试用 QTableWidget 和良好的参数显示一个新窗口:

class Parameters(QWidget):
  
    def __init__(self):
        super(Parameters, self).__init__()

        self.matrixsize = QLineEdit()
        bouton = QPushButton("define matrix_size")
        bouton.clicked.connect(self.appui_bouton)
        self.halfmatrix = QCheckBox()
        self.halfmatrix.toggled.connect(self.on_checked)

   
        self.define_matrix_size = QGroupBox('Define Parameters')
        layout = QGridLayout()
        layout.addWidget(self.matrixsize, 0, 0, 1, 1, )
        layout.addWidget(bouton, 0, 1, 1, 1)
        layout.addWidget(QLabel('select half size mode'
                                ), 1, 0, 1, 1)
        layout.addWidget(self.halfmatrix, 1, 1, 1, 1)
        self.define_matrix_size.setLayout(layout)

        process = QPushButton('process')
        process.clicked.connect(self.process)

        self.matrix = QTableWidget()
        self.layout = QGridLayout()
        self.layout.addWidget(self.define_matrix_size)
  
        self.layout.addWidget(matrix)
        self.layout.addWidget(process)

        self.setLayout(self.layout)

    def matrix_size(self):
        if self.matrixsize.text() == "":
            return 0

        else:
            return int(self.matrixsize.text())

       def appui_bouton(self):
        taille = self.matrixsize()
        self.matrix.deleteLater()
        if self.halfmatrix.isChecked():
            self.on_checked()

        else:
            self.matrix = QTableWidget()
            self.matrix.setColumnCount(taille)
            self.matrix.setRowCount(taille)
            self.layout.addWidget(self.matrix)
            self.update()
            self.setLayout(self.layout)

  


    def keyPressEvent(self, qKeyEvent):
        print(qKeyEvent.key())
        if qKeyEvent.key() == Qt.Key_Return or qKeyEvent.key() == Qt.Key_Enter:
            self.appui_bouton()
        else:
            super().keyPressEvent(qKeyEvent)

    def on_checked(self):
        taille = self.matrixsize()
        if taille == 0:
            pass

        else:
            if self.halfmatrix.isChecked():


                size = int(taille / 2)
                self.matrix.deleteLater()
                self.matrix = QTableWidget()
                self.matrix.setColumnCount(size)
                self.matrix.setRowCount(size)
                self.layout.addWidget(self.matrix, 3, 0, 20, 4)
                self.update()

                self.setLayout(self.layout)

            else:
                self.appui_bouton()

    def process (self):
        
        layout = QHBoxLayout()

        test = self.matrix
        test.setLayout(layout)
        test.show()

所以为了澄清我所说的:我有一个窗口,您可以在其中获取一些参数 (size,...) ,当您选择这些参数时,假设您采用 matrixsize==5,那么 5x5 表是添加到窗口。此表可以在此填充后由其他参数(我在代码上剪切它们)通过拖放系统进行。 所以现在我有了一个构建表,我希望能够通过单击“进程”按钮打开一个只包含表的新窗口。 所以我不想要一个动态表,我只想要一个保持相同属性的表(例如,如果矩阵启用了 Dragonly,那么新矩阵应该具有相同的属性)。我想保留单元格中包含的所有信息

我希望我足够清楚这是我第一次提问(当然是在多次阅读一些答案之后^^) 感谢您的回答和建议!

【问题讨论】:

你的意思是process中的表格应该根据矩阵大小来创建行和列吗? 不,我的意思是:在第一个选项卡中,我可以创建一个包含所需行数的表格(我断言它是一个正方形)。我可以用我想要的任何东西来填充它。我想要的是,当我单击“进程”时,会出现一个带有同一张表的新窗口。 (这是我想要跨过的第一步,之后,我希望单击进程创建一个新窗口,该窗口具有相同的表,并基于数据函数进行演变)。我希望我更清楚 第一个答案发错了,我更正了,现在清楚了吗? 嗯,这部分取决于你要对“新”表做什么:它应该是可编辑的吗?编辑后的数据是否应该与原始表动态同步?此外,您的示例不可重现,它缺少您要连接的两个函数(appui_boutonon_checked),并且没有关于实际应用表大小的任何痕迹。请编辑问题并使其代码可重现,包括设置表格大小所需的所有功能。 通常这样,它回答了你提出的问题@musicamante 【参考方案1】:

您可以创建一个没有父级的新 QTableWidget(这使其成为***窗口),然后显示它:

class Parameters(QWidget):
    # ...
    def process(self):
        rows = self.matrix.rowCount()
        columns = self.matrix.columnCount()
        self.newTable = QTableWidget(rows, columns)
        for row in range(rows):
            for column in range(columns):
                source = self.matrix.item(row, column)
                if source:
                    self.newTable.setItem(row, column, QTableWidgetItem(source))
        self.newTable.show()

请注意,我将新表创建为实例属性。这可以避免垃圾收集,以防它是一个局部变量(导致小部件显示并立即消失),但不幸的是,如果您再次单击进程按钮并且窗口已经存在,它将被删除并用新窗口“覆盖”。如果你想同时拥有更多的进程窗口,你可以将它们添加到一个列表中:

class Parameters(QWidget):
    def __init__(self):
        super(Parameters, self).__init__()
        # ...
        self.processTables = []

    def process(self):
        rows = self.matrix.rowCount()
        columns = self.matrix.columnCount()
        # note that now "newTable" is *local*
        newTable = QTableWidget(rows, columns)
        self.processTables.append(newTable)
        # ...

关于您的代码的一些建议:

绝对没有必要在每次想要更改其大小时都创建一个新表;只需在现有值上使用setRowCountsetColumnCount,如果您不想保留以前的值,请使用clear(); 不要使用两个功能几乎相同的函数(appui_boutonon_checked)并相互调用,只使用一个函数来检查这两个方面; 不要不必要地调用update():当你改变一个小部件的属性(或添加一个新的小部件到一个布局)update已经被调用了;虽然这不是一个实际问题(Qt 会自动管理 何时 更新实际发生,避免在不必要时重新绘制),调用它只会给您的代码添加不必要的噪音; 向网格布局添加小部件时要更加小心(我指的是on_checked 上的代码):如果不需要,不要使用rowSpan 和columnSpan;此外,使用高值是完全没有用的,因为该行中没有其他小部件,并且该布局中实际上只有一列;另外,不要再拨打setLayout(); 如果您需要数值,请使用QSpinBox,而不是 QLineEdit。

更新现有表格的功能可以更容易地重写,您应该将按钮复选框连接到它:

class Parameters(QWidget):
    def __init__(self):
        super(Parameters, self).__init__()
        self.matrixsize = QSpinBox()
        bouton = QPushButton("define matrix_size")
        bouton.clicked.connect(self.appui_bouton)
        self.halfmatrix = QCheckBox()
        self.halfmatrix.toggled.connect(self.appui_bouton)
        # ...

    def appui_bouton(self):
        taille = self.matrixsize.value()
        if self.halfmatrix.isChecked():
            taille //= 2
        if not taille:
            return
        self.matrix.setColumnCount(taille)
        self.matrix.setRowCount(taille)

【讨论】:

非常感谢您的长评论,我今天会试试这个,看看它在我的代码上是如何工作的

以上是关于如何通过单击 QPushButton 打印 QTableWidget的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5 (Python):通过 contextmenu 从 qpushbutton 获取值

PySide:如何在 QPushButton 单击槽中获取单击的 QPushButton 对象?

单击PushButton时如何在多个QLabel中打印?

如何使用 QEvents 在 Qt 中模拟 QPushButton 单击

单击时移除 QPushButton 周围的方格边框

丢弃点击的 QPushButton