Python PyQt - QTableWidget、JSON和emitSignal导致单元格空白

4

我正在使用PyQt开发一个简单的应用程序,用于读取包含JSON格式字符串的日志文件,并将其在表格中漂亮地输出。

除了在尝试从“load”函数中发出信号时,一切都按预期工作。这个信号会被主窗口捕获,在一个槽中重新排列带有新信息的表格。

如果没有发出信号,表格将完全正确地填充:

正常视图,无信号

通过取消注释self.emit,使信号被发出后,表格最终变得不完整:

信号已发出,空白单元格

如您所见,在第一张图片中,表格未排序,但所有字段都填充了。在第二张图片中,表格已排序,但某些字段为空!

用于填充表格和发送信号的代码:

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

接收信号并执行的代码:
#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)

程序的流程如下:program_init->register_signal。当用户执行打开日志的操作时,将调用openLog函数,该函数会填充表格/发出信号->接收到信号/resort table。
为了实现此方法,我使用了信号和槽机制,如果不这样做,QT/Python会抛出一堆关于无法安全地从函数中重绘GUI/Pixmap的警告。
问题: 如何使QTableWidget按照我所需的列进行排序,同时确保表格已完全填充?
2个回答

10
我认为解决方案是在填充表格时调用QTableWidget.setSortingEnabled(False)来禁用排序,然后再恢复排序。
例子代码:
#!/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_())

在您的示例中添加setSortingEnabled选项确实给了我期望的行为。 setSortingEnabled(False)需要在setRowCount()调用之前,而且信号发出后需要加上setSortingEnabled(True)。谢谢。 - PenguinCoder
这个解决方案结束了无尽的挫败感。谢谢! - Ryan

0

我一直在做类似的事情,但没有设置排序。我尝试了两种方法,两种方法都对我有效。

我的列表是一个字典列表,与你的略有不同。

我创建了一个tabledialog类,其中包含我的表格小部件,并从我的主窗口调用此函数:

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)

我也尝试在我的tablesetup函数的结尾使用:

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

并在我的主窗口的init部分设置插槽:

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

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

而且这个函数被称为:

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

我的表格小部件设置函数:

    # 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

我从不将排序设置为false,因为上面的答案建议。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接