【问题标题】:Cannot connect PySide QTableView selectionChanged signal无法连接 PySide QTableView selectionChanged 信号
【发布时间】:2015-09-12 15:50:23
【问题描述】:

我正在设计一个由 3D 查看器和一个带有 Python 3.4 和 PySide 绑定的表组成的程序。

我已经用这个类创建了一个 TableView:

from PySide import QtGui
from PySide.QtCore import Qt

class MyTableView(QtGui.QWidget):

    def __init__(self, parent=None):
        super(MyTableView, self).__init__()
        self.parent = parent
        self.title = "Results"
        self.initUI()

    def initUI(self):
        self.grid = QtGui.QGridLayout(self)

        self.table = QtGui.QTableView()
        self.grid.addWidget(self.table, 0, 0)
        # Configure table
        self.table.verticalHeader().setVisible(False)
        self.table.horizontalHeader().setDefaultAlignment(Qt.AlignLeft)
        self.table.setSortingEnabled(True)
        self.table.setAlternatingRowColors(True)
        self.table.setShowGrid(False)
        self.table.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers)
        self.table.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)

还有这个其他类的模型:

class MyModel(QStandardItemModel):

    def __init__(self, path, *args, **kwargs):
        super(MyModel, self).__init__()
        self.path = path
        self.parse()

    def parse(self):
        with open(self.path) as f:
            self.mydata = yaml.load(f)

        self.setColumnCount(len(self.mydata['headers']) + 1)
        self.setHorizontalHeaderLabels(
            ['ID'] + self.mydata['headers'])
        row = 0
        for ind, val in self.mydata['rows'].items():
            col = 0
            self.insertRow(row)
            self.setItem(row, col, QStandardItem(ind))
            for v in val:
                col += 1
                self.setItem(row, col, QStandardItem(str(v)))

            row += 1

然后在这个控制器中绑定在一起:

from PySide.QtCore import Qt

class MyController(object):

    def __init__(self, model, view):
        self.model = model
        self.tableview = view.table
        self.fill_table()
        self.connect_signals()

    def fill_table(self):
        self.tableview.setModel(self.model)
        self.tableview.sortByColumn(0, Qt.AscendingOrder)

    def connect_signals(self):
        selectionModel = self.tableview.selectionModel()
        selectionModel.selectionChanged.connect(self.selection_changed)

    def selection_changed(self, selected, deselected):
        print("Selection changed.")

然后,程序通过这个脚本执行:

def main():
    app = QtGui.QApplication(sys.argv)
    MyController(MyModel(sys.argv[1]), MyView())
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

(请注意,我没有发布主窗口类,但你明白了)

表格渲染正常,但我无法将 selectionChanged 信号连接到处理程序(这应该更新查看器,但出于测试目的,它只是一个打印语句)。

我做错了什么?谢谢!

[编辑] 我发现如果我使用 lambda 函数来调用处理程序方法,它就可以工作。谁能解释一下为什么?!

selectionModel.selectionChanged.connect(lambda: self.selection_changed(selectionModel.selectedRows()))

【问题讨论】:

    标签: python pyside


    【解决方案1】:

    我尝试实现您所写的内容并且效果很好 - 所以我不能 100% 确定您遇到问题的原因。但我怀疑这是因为我必须修复它才能让它工作:我必须解决你在垃圾收集方面遇到的一些问题。

    在您提供的示例代码中,您创建了一个MyController、一个MyModel 和一个MyView。但是它们都将被垃圾收集(在 CPython 中),因为您不保留对它们的引用。如果添加对MyController的引用

    my_controller = MyController(MyModel(sys.argv[1]), MyView())
    

    你快到了,但我认为 MyTableView 也可能会被垃圾回收,因为控制器只保留对 QTableVIew 的引用,而不是 MyTableView

    大概使用 lanbda 函数会更改您正在保留的引用 - 它保留了控制器和选择模型 - 这可能就是它在这种情况下工作的原因。

    一般来说,使用 Qt 父子机制是个好主意。如果您只是在主窗口(或它们的自然父窗口小部件)上设置所有这些对象的父级,则可以避免大多数这些问题。

    【讨论】:

    • 不敢相信!有用。我没有考虑到 GC 的后果……非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 2014-02-11
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多