Search code examples
pythonpyqtpyqt5qtablewidgetqtablewidgetitem

pyqt5 "QTableWidget" and "setItem" issue


I want to use QTableWidgetItem but something wrong.. I think the algorithm is as follows.

push bottom("apply") -> change Table widget items (But nothing change...)

here my python code... Please pay attention to the comments.

# -*- coding: utf-8 -*-
[..import..]

class UserModel(QStandardItemModel):
    [..item modeling for combobox..]

class Tab_1(QWidget):
    def __init__(self, API, parent=None):
        super(Tab_1, self).__init__(parent=parent)
        self.API = API
        self.ipaddr = []
        self.init_widget()


    def init_widget(self):
        [..GropBox & Layout define..]

        #### ComboBox define
        manufacturer = ["a", "b", "c"]
        combo_model = UserModel(manufacturer)
        combobox = QComboBox()
        combobox.setModel(combo_model)
        combobox.currentTextChanged.connect(self.select_manufacturer)

        [..pushbotton define..]
        pushbottom_list[1].released.connect(self.apply) ## connect Slot


    [..combo box event..]

    #### Push bottom Event
    def apply(self): ## apply button slot
        main = main1()
        print("apply")
        item = ["a", "b", "c", "d", "1", "2"]
        main.table_add_item(item) ## call

main window class!!

class main1(QMainWindow):
    def __init__(self):
        super(QMainWindow, self).__init__()
        self.initUI()

    def initUI(self):
        [..menuBar define..]

        self.table = QTableWidget(self)
        self.table.setGeometry(0, 21, 300, 700)
        self.table.setRowCount(200)
        self.table.setColumnCount(1)

        self.tbw = QTabWidget(self)
        self.tbw.setGeometry(300,21,400,500)
        self.tbw.addTab(Tab_1("API"), "Search API")

        [..layout define..]

    def status_msg(self, msg):
        self.sb.showMessage(msg)

    def table_add_item(self, item): ## setItem...
        for i in range(len(item)):
            print(item[i]) ## work
            self.table.setItem(i, 0, QTableWidgetItem(item[i])) ## Not Working!!! and nothing changed......

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = main1()
    ex.show()
    sys.exit(app.exec_())

Solution

  • The problem is simple, and shows that you have forgotten the basic concepts of OOP: classes are abstractions of the behavior of a set of elements, that is, each time you use the class to create an object, that object is different from the previous one (except that behavior is modified).

    In your case, the ex object of the class main1:

    ex = main1()
    

    is different to:

    main = main1()
    

    In the previous command you are creating a new window, and that window has its own QTableWidget, and you are adding those values ​​to that QTableWidget.

    You will say: if I am creating a window why it is not shown?, firstly because you do not call show, and secondly it is because it is a local variable that is eliminated when it finishes executing apply.

    The solution is simple, get the original main1, and for this there are several methods:

    • Using the parent() method:

      def apply(self): ## apply button slot
          print("apply")
          main =self.parent().parent().parent()
      
          items = ["a", "b", "c", "d", "1", "2"]
          main.table_add_item(items) ## call
      
    • Using the topLevelWidgets() method:

      def apply(self): ## apply button slot
          main = [w for w in QApplication.topLevelWidgets() if isinstance(w, main1)][0]
          items = ["a", "b", "c", "d", "1", "2"]
          main.table_add_item(items) ## call
      

    another alternative method is that you explicitly pass that object to the constructor of class Tab_1.

    Finally, the table_add_item method could be made more readable

    def table_add_item(self, items):
        for i, text in enumerate(items):
            self.table.setItem(i, 0, QTableWidgetItem(text))