2015-09-11 35 views
0

我正在设计一个由3D查看器和一个包含Python 3.4和PySide绑定的表组成的程序。无法连接PySide QTableView selectionChanged信号

我已经创建了一个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() 

(请注意,我没有贴主窗口类,但你的想法)

表获取呈现OK,但我不能给的SelectionChanged信号连接到处理器(应该udpate查看器,但出于测试目的,它只是一个打印语句)。

我在做什么错?谢谢!

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

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

回答

0

我试图实现你所写的和它的工作 - 所以我不能100%确定你为什么遇到问题。但我怀疑这是因为我必须解决这个问题才能解决问题:我必须理清垃圾回收的一些问题。

在示例代码中,您创建了一个MyController,一个MyModel和一个MyView。但是他们都会被垃圾收集(在CPython中),因为你没有提及它们。如果你添加一个引用MyController

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

你就要成功了,但我觉得MyTableView也可能再被垃圾收集,因为控制器只保留到QTableVIew不是MyTableView参考。

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

通常使用Qt父母机制是一个好主意。如果你简单地将所有这些对象放在主窗口(或它们的自然父窗口部件)上,这样可以防止大部分这些问题。

+0

不敢相信!有用。我没有考虑到GC的后果...感谢一堆! –