2016-10-31 7 views
6

QFileSystemModelQListViewを持っています。 QTreeViewの選択に基づいて、QListViewにはフォルダの内容が表示されます。
これで、いくつかの条件によってファイル名の色を変更する必要があります。
初期の考え方は、QListView内の項目を繰り返し処理し、条件が満たされているかどうかによって各項目の色を設定することです。 QFileSystemModelsetData()方法が唯一のようなものを無視して、EditRoleへの変更を受け入れるため、しかし、これは、不可能であるように思わQFileSystemModelに接続されたQListViewのファイルの色を条件付きで変更します。

self.FileModel.setData(index, QtGui.QBrush(QtCore.Qt.red), role=QtCore.Qt.ForegroundRole) 

これもhere 指摘されており、後者では提案はした[this見ます]サブクラスQItemDelegateは、QListView内の項目を色分けするために使用します。

従って、QStyledItemDelegateをサブクラス化し、paint()メソッドを再実装して、ファイル名が緑色で表示されるようにしました。しかし、今や醜いように見える:ファイルアイコンが失われ、 "mouse_over"エフェクトはもう働かない。

このサブクラスはとにかく汚い回避策ですが

、私のトップレベルの質問は、条件に基づいて QFileSystemModelに接続 QListView内の項目を色付けする方法はあり

  • でしょうか?

は今

  • はバック素敵な選択とアイコンで元の動作を取得する方法はあり、これはケースとQItemDelegateのサブクラスに付着しないかもしれないことを提供しますか?
  • QListViewのQFileSystemModelにどのItemDelegateがもともと使用されていることを知っている人はいますか?
  • ソースコードを取得してそこからペイントメソッドをコピーすることは可能ですか?

ここでは、サブクラス化を使用し、記述された動作を示す最小限のコードを示します。その文字列を含むすべてのファイルが緑色で強調表示されるように、文字列に入力できるのはQLineEditです。

import sys 
from PyQt4 import QtGui, QtCore 


class MyFileViewDelegate(QtGui.QStyledItemDelegate): 
    def __init__(self, parent=None, *args, **kwargs): 
     QtGui.QItemDelegate.__init__(self, parent, *args) 

     self.condition = None 
     self.isMatch = False 

     self.brush_active =   QtGui.QBrush(QtGui.QColor("#79b9ed")) 
     self.brush_active_matched = QtGui.QBrush(QtGui.QColor("#58cd1c")) 
     self.pen =     QtGui.QPen(QtGui.QColor("#414141")) 
     self.pen_matched =   QtGui.QPen(QtGui.QColor("#39c819")) 
     self.pen_active =   QtGui.QPen(QtGui.QColor("#eef2fd")) 
     self.pen_active_matched = QtGui.QPen(QtGui.QColor("#e7fade")) 


    def paint(self, painter, option, index): 
     text = index.data(QtCore.Qt.DisplayRole) 
     self.matchText(text) 

     painter.save() 
     ######## set background 
     painter.setPen(QtGui.QPen(QtCore.Qt.NoPen)) 
     if option.state & QtGui.QStyle.State_Selected: 
      if self.isMatch: 
       painter.setBrush(self.brush_active_matched) 
      else: 
       painter.setBrush(self.brush_active) 

     painter.drawRect(option.rect) 
     ######## set font color 
     if option.state & QtGui.QStyle.State_Selected: 
      if self.isMatch: 
       painter.setPen(self.pen_active_matched) 
      else: 
       painter.setPen(self.pen_active) 
     else: 
      if self.isMatch: 
       painter.setPen(self.pen_matched) 
      else: 
       painter.setPen(self.pen) 

     painter.drawText(option.rect, QtCore.Qt.AlignLeft, text) 

     painter.restore() 

    def matchText(self, filename): 
     # testing condition. In the real case this is much more complicated 
     if (self.condition != None) and (self.condition != "") and (self.condition in filename): 
      self.isMatch = True 
     else: 
      self.isMatch = False 

    def setCondition(self, condition): 
     self.condition = condition 


class MainWidget(QtGui.QWidget): 
    def __init__(self, parent=None, useDelegate = False): 
     super(MainWidget, self).__init__(parent) 
     self.setLayout(QtGui.QVBoxLayout()) 

     self.FolderModel = QtGui.QFileSystemModel() 
     self.FolderModel.setFilter(QtCore.QDir.NoDotAndDotDot | QtCore.QDir.AllDirs) 
     self.FolderModel.setRootPath("") 

     self.FolderView = QtGui.QTreeView(parent=self) 
     self.FolderView.setModel(self.FolderModel) 

     self.FolderView.setHeaderHidden(True) 
     self.FolderView.hideColumn(1) 
     self.FolderView.hideColumn(2) 
     self.FolderView.hideColumn(3) 
     self.FolderView.expanded.connect(self.FolderView.scrollTo) 
     self.FolderView.clicked[QtCore.QModelIndex].connect(self.browserClicked) 

     self.FileModel = QtGui.QFileSystemModel() 
     self.FileModel.setFilter(QtCore.QDir.NoDotAndDotDot | QtCore.QDir.Files) 

     self.FileView = QtGui.QListView(parent=self) 
     self.FileView.setModel(self.FileModel) 

     self.FileViewDelegate = None 
     if useDelegate: 
      self.FileViewDelegate = MyFileViewDelegate() 
      self.FileView.setItemDelegate(self.FileViewDelegate) 

     self.FileView.setSelectionMode( QtGui.QAbstractItemView.ExtendedSelection ) 

     self.LineEdit = QtGui.QLineEdit() 
     self.LineEdit.textChanged.connect(self.changeCondition) 

     # Add Widgets to layout 
     self.layout().addWidget(self.FolderView) 
     self.layout().addWidget(self.FileView) 
     self.layout().addWidget(self.LineEdit) 

    def changeCondition(self, text): 
     if self.FileViewDelegate: 
      self.FileViewDelegate.setCondition(text) 

    def browserClicked(self, index): 
     # the signal passes the index of the clicked item 
     # set the FileView's root_index to the clicked index 
     dir_path = self.FileModel.filePath(index) 
     root_index = self.FileModel.setRootPath(dir_path) 
     self.FileView.setRootIndex(root_index) 


class App(QtGui.QMainWindow): 
    def __init__(self, parent=None, useDelegate=False): 
     super(App, self).__init__(parent) 
     self.central = MainWidget(parent =self, useDelegate=useDelegate) 
     self.setCentralWidget(self.central) 

if __name__=='__main__': 
    app = QtGui.QApplication(sys.argv) 
    thisapp = App(None, True) # set False to view App without custom FileViewDelegate 
    thisapp.show() 
    sys.exit(app.exec_()) 

これは、それはとしてQItemDelegateをサブクラス化せずにどのように見えるかの比較である:

enter image description here

だけ言及し、このコードの別の問題は、一度条件が変更されていること、である、1人のニーズマウスをQFileViewに移動して再描画を開始します。私はそれを直接行うためにLineEdit.textChangeシグナルに接続するためにどのスロットを使うことができるのだろうと思います。

答えて

3

アイテムデリゲートの必要はありません。それはQFileSystemModeldata方法を再実装することにより、はるかに簡単に達成することができます。これは完璧に動作

class FileSystemModel(QtGui.QFileSystemModel): 
    def __init__(self, *args, **kwargs): 
     super(FileSystemModel, self).__init__(*args, **kwargs) 
     self.condition = None 

    def setCondition(self, condition): 
     self.condition = condition 
     self.dataChanged.emit(QtCore.QModelIndex(), QtCore.QModelIndex()) 

    def data(self, index, role=QtCore.Qt.DisplayRole): 
     if self.condition and role == QtCore.Qt.TextColorRole: 
      text = index.data(QtCore.Qt.DisplayRole) 
      if self.condition in text: 
       return QtGui.QColor("#58cd1c") 
     return super(FileSystemModel, self).data(index, role) 

class MainWidget(QtGui.QWidget): 
    def __init__(self, parent=None, useDelegate = False): 
     super(MainWidget, self).__init__(parent) 
     ... 
     self.FileModel = FileSystemModel(self) 
     ... 

    def changeCondition(self, text): 
     self.FileModel.setCondition(text) 
+0

。解決策を探すときに、なぜこのようなモデルのサブクラス化が見つからないのだろうと思います。これは一般的に行われていないのですか、それとも何か欠点がありますか? @ImportanceOfBeingErnest。 – ImportanceOfBeingErnest

+0

QtはPythonの[TOOWTDI](http://wiki.python.org/moin/TOOWTDI)アプローチに従わないようです - 特定の問題を解決するためにいくつかの方法を提供することがよくあります。サブクラス化はおそらく最も一般的に使用されるアプローチですが、関心のあるメソッドを有効に再実装できるかどうか(つまり、それらが仮想メソッドであるかどうか)によって明らかに異なります。 – ekhumoro

関連する問題