2014-09-11 35 views
-1

有一個包含三個鍵的字典:'Animals','Birds'和'Fish'。什麼設計邏輯與鏈接的ViewLists一起使用

主對話框有兩個列表視圖。左側視圖viewA顯示上述鍵的列表。 當其中一個項目被點擊時,正確的視圖viewB顯示物種的列表。

問題是如何管理viewB的顯示...假設用戶點擊「動物」:listB繼續,併爲列表中的每個動物構建一個全新的QListWidgetItem列表。然後用戶點擊「鳥」。我應該怎麼做已經建立viewB的「動物」項目?我應該隱藏它們嗎? (隱藏「動物」項目(而不是刪除)將允許我稍後再次點擊「動物」時隱藏它們(如果ListItems在圖形上很重:拇指,圖標等,則總是有意義的。如果動物列表是1000+將從頭開始重建ListItems,並取消隱藏最後一次點擊構建的區別)
我看到的另一種方法是用戶viewB.clear()每次點擊viewA的項目,因此listB項目每隔時間listA項目被點擊,但正如我與項目的一長串提到它可能是很慢。什麼邏輯在這樣的情況下實現?

enter image description here

from PyQt4 import QtCore, QtGui 
app=QtGui.QApplication(sys.argv) 

class Window(QtGui.QWidget): 
    def __init__(self): 
     super(Window, self).__init__() 
     layout=QtGui.QHBoxLayout() 
     self.setLayout(layout)   

     self.viewA=QtGui.QListWidget() 
     self.viewA.addItems(elements.keys()) 
     self.viewA.itemClicked.connect(self.aClicked) 
     self.viewB=QtGui.QListWidget() 

     layout.addWidget(self.viewA) 
     layout.addWidget(self.viewB) 
     self.show() 

    def aClicked(self, item): 
     key='%s'%item.text() 
     values=elements.get(key) 
     items=[QtGui.QListWidgetItem(val) for val in values] 
     result=[self.viewB.addItem(item) for item in items] 

elements={'Animals':['Bison','Panther','Elephant'],'Birds':['Duck','Hawk','Pigeon'],'Fish':['Shark','Salmon','Piranha']} 
window=Window() 
sys.exit(app.exec_()) 

回答

0

使用了兩種觀點的單一模式:而QListView和QTableView中: enter image description here

import os,sys 
from PyQt4 import QtCore, QtGui 
app=QtGui.QApplication(sys.argv) 
elements={'Animals':{1:'Bison',2:'Panther',3:'Elephant'},'Birds':{1:'Duck',2:'Hawk',3:'Pigeon'},'Fish':{1:'Shark',2:'Salmon',3:'Piranha'}} 

class DataModel(QtCore.QAbstractTableModel): 
    def __init__(self): 
     QtCore.QAbstractTableModel.__init__(self) 
     self.modelDict={}  
     self.items=[]  
    def rowCount(self, parent=QtCore.QModelIndex()): 
     return len(self.items) 

    def columnCount(self, index=QtCore.QModelIndex()): 
     return 4 

    def data(self, index, role): 
     if not index.isValid() or not (0<=index.row()<len(self.items)): return QtCore.QVariant() 
     key=str(self.items[index.row()]) 
     column=index.column() 

     if role==QtCore.Qt.ItemDataRole: return self.modelDict.get(str(index.data().toString())) 

     if role==QtCore.Qt.DisplayRole: 
      if column==0: 
       return key 
      else: 
       return self.modelDict.get(key).get(column) 

    def addItem(self, itemName=None, column=0): 
     totalItems=self.rowCount()+1 
     self.beginInsertRows(QtCore.QModelIndex(), totalItems, column) 
     if not itemName:   itemName='Item %s'%self.rowCount() 
     self.items.append(itemName) 
     self.endInsertRows() 

    def buildItems(self): 
     for key in self.modelDict: 
      index=QtCore.QModelIndex() 
      self.addItem(key) 

class ProxyTableModel(QtGui.QSortFilterProxyModel): 
    def __init__(self, parent=None): 
     super(ProxyTableModel, self).__init__(parent) 

    def headerData(self, column, orientation, role=QtCore.Qt.DisplayRole): 
     if role == QtCore.Qt.TextAlignmentRole: 
      if orientation == QtCore.Qt.Horizontal: 
       return QtCore.QVariant(int(QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)) 
      return QtCore.QVariant(int(QtCore.Qt.AlignRight|QtCore.Qt.AlignVCenter)) 
     if role != QtCore.Qt.DisplayRole: 
      return QtCore.QVariant() 

     if orientation==QtCore.Qt.Horizontal: 
      if column==1: 
       return QtCore.QVariant("Species 1") 
      elif column==2: 
       return QtCore.QVariant("Species 2") 
      elif column==3: 
       return QtCore.QVariant("Species 3") 

     return QtCore.QVariant(int(column + 1)) 

class Window(QtGui.QWidget): 
    def __init__(self): 
     super(Window, self).__init__() 
     mainLayout=QtGui.QHBoxLayout() 
     self.setLayout(mainLayout) 

     self.dataModel=DataModel() 
     self.dataModel.modelDict=elements 
     self.dataModel.buildItems() 

     self.proxyModel=ProxyTableModel() 
     self.proxyModel.setFilterKeyColumn(0)  
     self.proxyModel.setSourceModel(self.dataModel) 

     self.viewA=QtGui.QListView() 
     self.viewA.setModel(self.dataModel) 
     self.viewA.clicked.connect(self.onClick) 

     self.viewB=QtGui.QTableView()   
     self.viewB.setModel(self.proxyModel) 
     self.viewB.setColumnHidden(0,True) 

     mainLayout.addWidget(self.viewA) 
     mainLayout.addWidget(self.viewB)  
     self.show() 

    def onClick(self): 
     index=self.viewA.currentIndex() 
     key=self.dataModel.data(index, QtCore.Qt.DisplayRole) 
     value=self.dataModel.data(index, QtCore.Qt.ItemDataRole)   
     self.proxyModel.setFilterRegExp('%s'%key) 
     print 'onClick(): key: %s'%type('%s'%key) 

window=Window() 
sys.exit(app.exec_()) 
1

我建議用Model-View的方法來代替。

您將有兩種型號:KeysModelValuesModelQAbstractListModelQStringListModel繼承。兩個視圖QTableViewKeysViewValuesView。和一個代理模型QSortFilterProxyModelProxyModel這將幫助您顯示由ValuesView中的鍵過濾的值。

當KeysView一個項目被選擇只是分配一個新的過濾器,以ProxyModel和值在ValuesView將被改變。

+0

請使用我的示例代碼來說明你的想法。沒有看到如何將它放在一起,很難理解這個概念。提前致謝! – alphanumeric 2014-09-11 06:11:20

+2

Sputnix,請閱讀@Ezee在他的回答中鏈接到的Model/View編程文檔。 「研究這個概念」後研究起來容易得多,而不是讓某人爲你做這些工作! – TheDarkKnight 2014-09-11 08:28:25

+0

我發佈的例子只有22行。爲了說明這個概念,需要花多長時間進行編輯?這個論壇不僅僅是指向文檔。 – alphanumeric 2014-09-11 14:02:44

0

在其他類QColumnView它可以設計數據的層次結構。嘗試閱讀文檔吧。

+0

太棒了!了不起!謝謝!這非常有幫助!使用'QColumnView'作爲關鍵字我現在可以整天Google! – alphanumeric 2014-09-11 14:10:49