2017-12-01 5 views
0

내 도구는 수천 개의 이미지를 반복하고 아래 그림과 같이 이미지의 축소판을 내 목록보기로로드합니다. 그러나 모든 이미지가 처리 될 때까지 내 응용 프로그램이 멈 춥니 다. UI로드가 중단되어 이미지가 목록 뷰에 채워질 수있는 방법이 있는지 궁금 해서요. UI가 멈추지 않도록하고 이미지가 채워진 상태에서 사용자가 응용 프로그램을 사용하도록할까요?QListview에 백그라운드에서 큰 데이터 세트를 채우십시오.

이것은 모두 파이썬과 파이사이드로 수행됩니다.

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() 

또 다른 솔루션은 이미지를로드하는 것입니다,하지만 그것을 위해 우리가 모델의 메소드 데이터를 덮어 써야합니다, 또한 우리는 저장하는 새 역할을 만들어야합니다 이미지의 경로가 아니라 QStandardItemModel에 대한 데이터 논리를 분석하면 SizeHintRole 역할을 호출 한 것을 발견했으며 DecorationRole 역할을 호출하여 동일한 오류를 생성하므로 미리 정의 된 크기를 넣어서 오류를 피할 수 있습니다. 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

와우 놀라운 일입니다. 두 번째 해결책은 내가하려는 일에 완벽하게 작동하는 것 같습니다. 두 가지 옵션 중에서 가장 성능이 좋은 것 같습니다. 따라서 항목이 스크롤 뷰 내에있을 때만 이미지를로드합니까? – JokerMartini

+0

처음 스크롤 할 때이 이미지가로드됩니다. 많은 양의 이미지가있는 경우 이미지를 저장하지 않는 것이 좋습니다.이 경우 램을 많이 사용하기 때문에 중간 솔루션을 제공합니다. – eyllanesc

+0

예 내 경우에는 최대 20,000 개의 이미지가있을 수 있습니다. 그 시점에서 당신은 무엇을 조언하겠습니까? 모든 이미지는 50x 품질의 256x256 JPEG입니다. – JokerMartini

관련 문제