2017-12-01 5 views
0

私のツールは、数千枚の画像をループし、下図のように私のリストビューに画像のサムネイルをロードします。しかし、私のアプリケーションは、すべての画像が処理されるまでフリーズします。それらは凍結し、ユーザーは、画像が取り込まれながらアプリケーションを使用することについて手放すからUIを防止し、ロードされたとして、私は、画像とリストビューを移入できた道があった場合、私は不思議でしたか?移入QListview

これは、すべて私たちのpythonとpysideが行われます。

enter image description here

コード:

import os 
import sys 
from PySide import QtGui, QtCore 

class Example(QtGui.QMainWindow): 

    def __init__(self): 
     super(Example, self).__init__() 
     self.resize(800, 400) 
     self.setWindowTitle('Image Viewer') 

     self.image_dir = "C:/Users/JokerMartini-Asus/Desktop/textures/thumbs" 

     self.ui_image_viewer = QtGui.QListView() 
     self.ui_image_viewer.setViewMode(QtGui.QListView.IconMode) 
     self.ui_image_viewer.setResizeMode(QtGui.QListView.Adjust) 
     self.ui_image_viewer.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) 
     self.ui_image_viewer.setIconSize(QtCore.QSize(300,300)) 
     self.ui_image_viewer.setMovement(QtGui.QListView.Static) 
     self.ui_image_viewer.setModel(QtGui.QStandardItemModel()) 

     for img in os.listdir(self.image_dir): 
      img_path = os.path.join(self.image_dir, img) 
      pixmap = QtGui.QPixmap(img_path) 

      name = os.path.splitext(os.path.basename(img_path))[0] 
      item = QtGui.QStandardItem(QtGui.QIcon(pixmap), name) 
      self.ui_image_viewer.model().appendRow(item) 

     # Layout 
     grid = QtGui.QVBoxLayout() 
     grid.setContentsMargins(10,10,10,10) 
     grid.addWidget(self.ui_image_viewer) 

     main_widget = QtGui.QWidget() 
     main_widget.setLayout(grid) 
     self.setCentralWidget(main_widget) 
     self.show() 

def main(): 

    app = QtGui.QApplication(sys.argv) 
    ex = Example() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 

答えて

1

過負荷を生成プロセスは、QPixmapのの作成ですので、我々は時間をかけてその負荷を分散する場合、我々はレスポンスを向上させることができ、我々はこれを行うことができますQTimerを介して。また、我々は店に新しい役割を作成する必要があり、

import os 
import sys 
from PySide import QtGui, QtCore 

class Example(QtGui.QMainWindow): 

    def __init__(self): 
     super(Example, self).__init__() 
     self.resize(800, 400) 
     self.setWindowTitle('Image Viewer') 

     self.image_dir = "C:/Users/JokerMartini-Asus/Desktop/textures/thumbs" 

     self.ui_image_viewer = QtGui.QListView() 
     self.ui_image_viewer.setViewMode(QtGui.QListView.IconMode) 
     self.ui_image_viewer.setResizeMode(QtGui.QListView.Adjust) 
     self.ui_image_viewer.setEditTriggers(QtGui.QAbstractItemView.NoEditTriggers) 
     self.ui_image_viewer.setIconSize(QtCore.QSize(300,300)) 
     self.ui_image_viewer.setMovement(QtGui.QListView.Static) 
     self.ui_image_viewer.setModel(QtGui.QStandardItemModel()) 

     self.imgs = iter(os.listdir(self.image_dir)) 
     timer = QtCore.QTimer(self) 
     timer.timeout.connect(self.load) 
     timer.start(100) 

     # Layout 
     grid = QtGui.QVBoxLayout() 
     grid.setContentsMargins(10,10,10,10) 
     grid.addWidget(self.ui_image_viewer) 

     main_widget = QtGui.QWidget() 
     main_widget.setLayout(grid) 
     self.setCentralWidget(main_widget) 
     self.show() 

    def load(self): 
     try: 
      img = next(self.imgs) 
      img_path = os.path.join(self.image_dir, img) 
      pixmap = QtGui.QPixmap(img_path) 
      name = os.path.splitext(os.path.basename(img_path))[0] 
      item = QtGui.QStandardItem(QtGui.QIcon(pixmap), name) 
      self.ui_image_viewer.model().appendRow(item) 
     except StopIteration: 
      self.sender().stop() 

def main(): 

    app = QtGui.QApplication(sys.argv) 
    ex = Example() 
    sys.exit(app.exec_()) 

if __name__ == '__main__': 
    main() 

別の解決策は、スクロールバーが移動したときに言うことです、必要なときにイメージをロードすることであろうが、そのために、我々は、モデルのメソッドデータを上書きする必要があります画像のパスが、私はSizeHintRoleの役割を呼ばれることを見出した、それが役割DecorationRole呼び出して、同じエラーが発生するので、それは避けように、私たちがやるべきことは事前に定義されたサイズを置いているQStandardItemModelのためのデータの論理を分析DecorationRoleを呼び出すと、オーバーロードを避けることができます。

import os 
import sys 

from PySide.QtCore import * 
from PySide.QtGui import * 


class StandardItem(QStandardItem): 
    PathRole = Qt.UserRole +1 

    def __init__(self, *args, **kwargs): 
     QStandardItem.__init__(self, *args, **kwargs) 
     self.path = "" 

    def setData(self, value, role=Qt.UserRole + 1): 
     if role == StandardItem.PathRole: 
      self.path = value 
     else: 
      QStandardItem.setData(self, value, role) 
      # self.emitDataChanged() 

    def data(self, role=Qt.UserRole+1): 
     if role == StandardItem.PathRole: 
      return self.path 
     return QStandardItem.data(self, role) 

    def type(self): 
     return Qt.UserType 


class StandardItemModel(QStandardItemModel): 
    def __init__(self, *args, **kwargs): 
     QStandardItemModel.__init__(self, *args, **kwargs) 
     self.setItemPrototype(StandardItem()) 

    def data(self, index, role=Qt.DisplayRole): 
     if role == Qt.DecorationRole: 
      it = self.itemFromIndex(index) 
      value = it.data(Qt.DecorationRole) 
      if value is None: 
       path = it.data(StandardItem.PathRole) 
       value = QIcon(QPixmap(path)) 
       it.setData(value, Qt.DecorationRole) 
      return value 
     elif role == Qt.SizeHintRole: 
      return QSize(300, 250) 
     else: 
      return QStandardItemModel.data(self, index, role) 


class Example(QMainWindow): 
    def __init__(self): 
     super(Example, self).__init__() 
     self.resize(800, 400) 
     self.setWindowTitle('Image Viewer') 

     self.image_dir = "C:/Users/JokerMartini-Asus/Desktop/textures/thumbs" 

     self.ui_image_viewer = QListView() 
     self.ui_image_viewer.setViewMode(QListView.IconMode) 
     self.ui_image_viewer.setResizeMode(QListView.Adjust) 
     self.ui_image_viewer.setEditTriggers(QAbstractItemView.NoEditTriggers) 
     self.ui_image_viewer.setIconSize(QSize(300, 300)) 
     self.ui_image_viewer.setMovement(QListView.Static) 
     self.ui_image_viewer.setModel(StandardItemModel()) 

     for img in os.listdir(self.image_dir): 
      img_path = os.path.join(self.image_dir, img) 
      name = os.path.splitext(os.path.basename(img_path))[0] 
      item = StandardItem(name) 
      item.setData(img_path) 
      self.ui_image_viewer.model().appendRow(item) 

     # Layout 
     grid = QVBoxLayout() 
     grid.setContentsMargins(10, 10, 10, 10) 
     grid.addWidget(self.ui_image_viewer) 

     main_widget = QWidget() 
     main_widget.setLayout(grid) 
     self.setCentralWidget(main_widget) 
     self.show() 


def main(): 
    app = QApplication(sys.argv) 
    ex = Example() 
    sys.exit(app.exec_()) 


if __name__ == '__main__': 
    main() 
+0

これは素晴らしいです。 2番目の解決策は、私がしようとしていることに完璧に働くようです。 2つのオプションの中で最もパフォーマンスが良いと思われます。これは、アイテムがスクロールビュー内にあるときにイメージをロードするだけですか? – JokerMartini

+0

それはあなたが大量の画像を持っている場合、私が中間の溶液を得、この場合には、それは多くのRAMを要するであろうから、それを保存しないことをお勧めし、それがスクロールして示されている最初の時間でそれをロードし – eyllanesc

+0

ええ私の場合は、おそらく最大20,000の画像があります。あなたはその時点で何をアドバイスしますか?すべての画像は256x256のJPEGで、50の品質を持っています – JokerMartini