Python PyQt - QTableWidget, JSON, and emitSignal causing blank cells

为君一笑 提交于 2020-01-01 03:37:09

问题


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

Everything is working as expected except when I try to emit a signal from a 'load' function. This signal is picked up by the main window, in a slot designed to resort the table with new information.

Without the signal emitted, the table populates fully and properly:

By uncommenting the self.emit so that the signal IS emitted, the table ends up being incomplete:

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

The code that populates the table and sends the 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"))

The code for receiving the signal, and acting:

#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 as : program_init->register_signal. User action to open log ->openLog function that populates table/emit signal->signal received/ resort table

For this method, I am using signals and slots, as if I do not, QT/Python throws a bunch of warnings about it not being safe to redraw the GUI/Pixmap from the function.

Question: How can I make the QTableWidget sort on the column I desire, while also ensuring the table is fully populated?


回答1:


I think solution is to disable sorting while populating table by calling QTableWidget.setSortingEnabled(False), and then restore sorting.

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



回答2:


I've been working on something similar, but was not setting up a sort. I tried both ways, and both worked for me.

My list, is a list of dictionaries, so 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 setup the slot in my main window, in the 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 the function called:

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

My tablewidget setup 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 don't bother ever set sorting to false, as the answer above mine recommends.



来源:https://stackoverflow.com/questions/9788592/python-pyqt-qtablewidget-json-and-emitsignal-causing-blank-cells

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!