artemisfowl2
artemisfowl2

Reputation: 1

How can I print a QTableWidget by clicking on QPushButton

I have an interface with two tab: in the first one i ask the user to enter parameters and in the second one i want to print the following QTableWidget.

So basically on the first tab i have a QPushButton that i called process and normally, when i push on it , i want to send the information to the second Tab.

Right now i just tried to show a new window with the QTableWidget and the good parameters :

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

So in order to clarify what i said: i have a Window on which you get some parameters (size,...) , when you select those parameters, let's say you take matrixsize==5, then a 5x5 table is added to the window. This table can be after this fill by others parameters (i cut them on the code) by a system of drag and drop. So now that i got a built table, i want to be able to open a new window with just the table by clicking on the ''process'' button. So i don't want a dynamical table, i just want a table that keeps the same property (for instance if the matrix has dragonly enable then the new matrix should have the same) . I want to keep every information containing in the cells

I hope i am enoughly clear that is my first time asking questions (after many times reading some answers of course^^) thanks for your answer and advice !

Upvotes: 0

Views: 376

Answers (1)

musicamante
musicamante

Reputation: 48499

You can just create a new QTableWidget with no parent (which makes it a top level window), and then show it:

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

Note that I created the new table as an instance attribute. This allows to avoid the garbage collection in case it was a local variable (resulting in the widget showing and disappearing right after), but has the unfortunate effect that if you click on the process button again and a window already exists, it gets deleted and "overwritten" with a new window. If you want to have more process windows at the same time, you could add them to a list:

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)
        # ...

Some suggestions about your code:

  • there's absolutely no need to create a new table each time you want to change its size; just use setRowCount and setColumnCount on the existing one, and if you don't want to keep previous values, use clear();
  • don't use two functions that do almost the same things (appui_bouton and on_checked) and call each other, just use one function that checks for both aspects;
  • don't call update() unnecessarily: when you change the properties of a widget (or add a new widget to a layout) update is called already; while it's not an actual issue (Qt automatically manages when updates actually happen, avoiding repainting if not necessary), calling it just adds unnecessary noise to your code;
  • be more careful when adding widgets to a grid layout (I'm referring to the code on on_checked): don't use the rowSpan and columnSpan if not required; also, using a value that high is completely useless, as there are no other widgets in that row, and there's actually only one column in that layout; also, don't call setLayout() again;
  • if you need a numerical value, then use a QSpinBox, not a QLineEdit.

The function to update the existing table can be rewritten more easily, and you should connect both the button and the checkbox to it:

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)

Upvotes: 1

Related Questions