1

I am trying to solve the sorting issue and found this answer: QTableWidget Integer

So I borrowed the code, and tried to test and fill multiple columns. However, the second column doesn't get filled for some reason. See below for the code I am using:

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QTableWidget, QTableWidgetItem, QVBoxLayout
from PyQt5.QtCore import Qt

class Widget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.widget_layout = QVBoxLayout()
        self.table_widget = QTableWidget(101, 2)
        self.table_widget.setSortingEnabled(True)

        self.widget_layout.addWidget(self.table_widget)
        self.setLayout(self.widget_layout)

        for num in range(101):
            item = QTableWidgetItem()
            item.setData(Qt.EditRole, num)
            self.table_widget.setItem(num, 0, item)
            item2 = QTableWidgetItem()
            item2.setData(Qt.EditRole, num)
            self.table_widget.setItem(num, 1, item2)

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

Not sure what went wrong here. Thanks!

2 Answers 2

4

The problem is that you enable sorting before adding items to the table. This means that the table is resorted every time a new item is added. If you scroll down to the bottom of the table in your example, you will see that the last row of the second column has a value. So what is happening is that the same cell of the second column is being set every time, due to the constant re-sorting.

In general, it's best to disable sorting whilst populating a table as it is much more efficient (as well as avoiding unexpected results). To fix your example, I would suggest moving the code into a separate method, like this:

class Widget(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.widget_layout = QVBoxLayout()
        self.table_widget = QTableWidget(101, 2)
        self.widget_layout.addWidget(self.table_widget)
        self.setLayout(self.widget_layout)
        self.fillTable()

    def fillTable(self):
        self.table_widget.clearContents()
        self.table_widget.setSortingEnabled(False)
        self.table_widget.sortByColumn(0, Qt.AscendingOrder)
        for num in range(101):
            item = QTableWidgetItem()
            item.setData(Qt.EditRole, num)
            self.table_widget.setItem(num, 0, item)
            item2 = QTableWidgetItem()
            item2.setData(Qt.EditRole, num)
            self.table_widget.setItem(num, 1, item2)
        self.table_widget.setSortingEnabled(True)
2

I will offer an explanation of what's happening behind the scenes here:

From what I can see after executing the script, everything seems normal. So why is that column 2 gets items only at the bottom row?

See.. the table's size is already set. There's a number of blank rows already pre-allocated on the table.

    1    2
  1 _    _
  2 _    _
  3 _    _
  4 _    _
  5 _    _
  6 _    _
  7 _    _
  8 _    _
  9 _    _
  . _    _
  . _    _
  . _    _
 99 _    _
100 _    _

When the first items are inserted, num==0, they do get inserted in both columns:

    1    2
  1 0    0    <-- both items are inserted at row 1
  2 _    _
  3 _    _
  4 _    _
  5 _    _
  6 _    _
  7 _    _
  8 _    _
  9 _    _
  . _    _
  . _    _
  . _    _
 99 _    _
100 _    _

However as sorting is enabled, and, look at this image here:

enter image description here

This arrow indicates that the first column is being sorted by default. When you're going to insert num==1 at the 2nd row, the first step is to insert it on column 1:

    1    2
  1 0    0
  2 1    _  <-- inserting num==1 at column 1
  3 _    _
  4 _    _
  5 _    _
  6 _    _
  7 _    _
  8 _    _
  9 _    _
  . _    _
  . _    _
  . _    _
 99 _    _
100 _    _

As the num==1 is inserted at column 1, and the sorting is enabled by default, the column 1 is sorted instantly after it's done:

    1    2
  1 1    _   <-- auto sorting is enabled on column 1. Rows are swapped.
  2 0    0
  3 _    _
  4 _    _
  5 _    _
  6 _    _
  7 _    _
  8 _    _
  9 _    _
  . _    _
  . _    _
  . _    _
 99 _    _
100 _    _

And now, we will insert num==1 on the next column:

    1    2
  1 1    _
  2 0    1    <-- See here? The value 0 was overwritten
  3 _    _
  4 _    _
  5 _    _
  6 _    _
  7 _    _
  8 _    _
  9 _    _
  . _    _
  . _    _
  . _    _
 99 _    _
100 _    _

This pattern repeats until we reach the bottom of the rows:

    1    2
  1 100  _
  2 99   _
  3 98   _
  4 97   _
  5 96   _
  6 96   _
  7 95   _
  8 94   _
  9 93   _
  . ..   _
  . ..   _
  . ..   _
 99  1   _
100  0   100

So, everything is working "exactly as planned". Not by you maybe, but to PyQt5, this is what it though you wanted to do when you enabled column sorting before inserting items on the table.

1
  • A small note: it's not about PyQt, it's just Qt. No matter what bindings are used, they rely on the behavior of the "base" library. Commented Jul 18, 2022 at 3:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.