2015-09-11 37 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的後果...感謝一堆! –