Python PyQt - QTableWidget, JSON and emitSignal causing empty cells

I am using PyQt for a simple application that reads from a log file with JSON formatted strings and outputs them perfectly to a table.

Everything works as expected, except when I try to emit a signal from the "load" function. This signal is picked up by the main window in the slot, designed to bring the table into new information.

Without the output signal, the table is filled completely and correctly:

Normal view, no signal

By uncommenting self.emit

for the IS signal to be emitted, the table ends up incomplete:

Signal emitted, blank cells

As you can see in the first image, the table is NOT sorted, but all fields are filled. In the second image, the table is sorted, but some fields are empty!

Code that populates the table and sends a signal:

#openLog function does stuff, then populates the table as follows

self.ui.tableWidget.setRowCount(len(entries))
self.ui.tableWidget.verticalHeader().setVisible(False)

for i, row in enumerate(entries):
    for j, col in enumerate(row):
        item = QtGui.QTableWidgetItem(col)
        self.ui.tableWidget.setItem(i, j, item)

#When this is uncommented, the table ends up having a lot of blank cells.
#self.emit(QtCore.SIGNAL("updateSignal"))

      

Code for receiving signal and action:

#main window class
    #__init__
        self.ui.tableWidget.connect(self,QtCore.SIGNAL("updateSignal"),self.updateTable)

    def updateTable(self):
        self.ui.tableWidget.sortItems(0,QtCore.Qt.DescendingOrder)

      

The program flow is called: program_init-> register_signal. User action to open log -> openLog function which populates signal / signal receive / receive table> / table

For this method I use signals and slots, as if I don't, QT / Python is throwing a bunch of warnings that it is not safe to redraw the GUI / Pixmap from a function.

Question:   How can I sort the QTableWidget on the desired column and also ensure that the table is completely populated?

+2


source to share


2 answers


I think the solution is to disable sorting when the table is populated by calling QTableWidget.setSortingEnabled(False)

and then re-establishing the sort.

Sample code:



#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
from PyQt4 import QtCore, QtGui

class MainWindow(QtGui.QWidget):
    updateSignal = QtCore.pyqtSignal()
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.table_widget = QtGui.QTableWidget()
        self.button = QtGui.QPushButton('Populate')
        self.button.clicked.connect(self.populate)
        layout = QtGui.QVBoxLayout()
        layout.addWidget(self.table_widget)
        layout.addWidget(self.button)
        self.setLayout(layout)
        self.updateSignal.connect(self.update_table)
        self.populate()

    def populate(self):
        nrows, ncols = 5, 2
        self.table_widget.setSortingEnabled(False)
        self.table_widget.setRowCount(nrows)
        self.table_widget.setColumnCount(ncols)
        for i in range(nrows):
            for j in range(ncols):
                item = QtGui.QTableWidgetItem('%s%s' % (i, j))
                self.table_widget.setItem(i, j, item)
        self.updateSignal.emit()
        self.table_widget.setSortingEnabled(True)

    def update_table(self):
        self.table_widget.sortItems(0,QtCore.Qt.DescendingOrder)


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    wnd = MainWindow()
    wnd.resize(640, 480)
    wnd.show()
    sys.exit(app.exec_())

      

+6


source


I've been working on something similar, but haven't set up. I tried both ways and both worked for me.

My list is a list of dictionaries that are slightly different from yours.

I have created a tabledialog class that contains my table widget and this function is called from my main window:

def setuptable(self, alist):

    # setup variables
    rows = len(alist)
    cols = len(alist[0])
    keys = ['number', 'name', 'phone', 'address'] # for dictonary order

    # setup cols, rows
    self.tableWidget.setRowCount(rows)
    self.tableWidget.setColumnCount(cols)

    # insert data
    for row in range(rows):
        for col in range(cols):
            item = QtGui.QTableWidgetItem()
            item.setText(alist[row][keys[col]] or '') # or '' for any None values
            table.setItem(row, col, item)

    keys = [item.title() for item in keys]  # capitalize
    self.tableWidget.setHorizontalHeaderLabels(keys) # add header names
    self.tableWidget.horizontalHeader().setDefaultAlignment(QtCore.Qt.AlignLeft) # set alignment
    self.tableWidget.resizeColumnsToContents() # call this after all items have been inserted

    self.tableWidget.sortItems(1,QtCore.Qt.AscendingOrder)

      

Also tried using at the end of my tablesetup function:

self.emit(QtCore.SIGNAL("loadingDone"))

      

and set up a slot in my main window under init section:



# setup the dialog
import dialogtable
self.tabledialog = dialogtable.dialogtable()

# signal from table dialog
self.tabledialog.connect(self.tabledialog,QtCore.SIGNAL("loadingDone"),self.tableSort)

      

And a function called:

def tableSort(self):
    self.tabledialog.tableWidget.sortItems(1,QtCore.Qt.AscendingOrder)

      

My table widget customization functions:

    # set table widget attributes
    self.tableWidget.setEditTriggers(QtGui.QAbstractItemView.DoubleClicked) # use NoEditTriggers to disable editing
    self.tableWidget.setAlternatingRowColors(True)
    self.tableWidget.setSelectionMode(QtGui.QAbstractItemView.NoSelection)
    self.tableWidget.verticalHeader().setDefaultSectionSize(18) # tighten up the row size
    self.tableWidget.horizontalHeader().setStretchLastSection(True) # stretch last column to edge
    self.tableWidget.setSortingEnabled(True) # allow sorting

      

I'm not worried about ever setting sorting to false as my answer above recommends mine.

0


source







All Articles