2012-10-26 3 views
1

다음 코드를 가지고 있으며 더 효율적으로 만들 수있는 방법이 있는지 궁금합니다. setCurrentItem() 및 scrollToItem() 함수는 프로세스를 상당히 느려지 게합니다. 또한 루프가 완료된 후 즉시 추가되는 대신 항목이 목록에 표시되는 것을 확인하고 싶습니다. 어떤 도움이나 토론이 크게 도움이 될 것입니다.PyQt4 QListWidget의 효율성을 어떻게 향상시킬 수 있습니까?

import sys 
from math import * 
#from PyQt4 import QtCore, QtGui 
from PyQt4.QtCore import (Qt, SIGNAL, QSize) 
from PyQt4.QtGui import (QApplication, QDialog, QLabel, QListWidget, QListWidgetItem,  QPushButton, QScrollArea, QTextDocument, QVBoxLayout) 
from time import localtime, strftime 
import time 

class LogDlg(QDialog): 

    def __init__(self, parent=None): 
    super(LogDlg, self).__init__(parent) 
    self.resize(450, 380) 

    self.log1 = QListWidget() 
    self.log2 = QListWidget() 
    lbl = QLabel() 
    lbl_2 = QLabel() 
    lbl.setText("Communications Log") 
    lbl_2.setText("Command/Data Log") 
    self.pushButton = QPushButton() 
    self.pushButton.setMaximumSize(QSize(110, 24)) 
    self.pushButton.setObjectName("pushButton") 

    self.pushbutton = QPushButton 
    self.pushButton.setText("Start Log Loop") 
    layout = QVBoxLayout() 
    layout.addWidget(self.pushButton) 
    layout.addWidget(lbl) 
    layout.addWidget(self.log1) 
    layout.addWidget(lbl_2) 
    layout.addWidget(self.log2) 
    self.setLayout(layout) 
    self.setWindowTitle("Transaction Logs") 
    self.connect(self.pushButton,SIGNAL("clicked()"),self.logLoop) 
    self.time = time.time() 

    def logLoop(self): 
    for i in range(1000): 
     print i 
     self.addLog("This is a test","c",True)  

    def timeStamp(self): 
    now = time.time() 
    localtime = time.localtime(now) 
    milliseconds = '%02d' % int((now - int(now)) * 100) 
    val = time.strftime('%H:%M:%S.', localtime) + milliseconds 
    return val 

    def clearUi(self): 
    self.log1.clear() 
    self.log2.clear() 

    def addLog(self, data, type="c", ts=False): 
#  pass 
    t = self.timeStamp() 
    if ts == True: 
     data = t + " " + data 
    if type == "c": 
     self.listItem1 = QListWidgetItem() 
     self.listItem1.setText(data) 
     self.log1.addItem(self.listItem1) 
#  self.log1.scrollToItem(self.listItem1) 
     self.log1.setCurrentItem(self.listItem1) 


    elif type == "d": 
     self.listItem2 = QListWidgetItem() 
     self.listItem2.setText(data) 
     self.log2.addItem(self.listItem2) 
#  self.log2.scrollToItem(self.listItem2) 
     self.log2.setCurrentItem(self.listItem2) 


app = QApplication(sys.argv) 
form = LogDlg() 
form.open() 
app.exec_() 

답변

1

귀하의 문제는 .scrollToItem 또는 .setCurrentItem와 아무 상관이 없습니다. logLoop 메서드의 루프는 Qt 이벤트 루프가 상황을 업데이트 할 수있는 기회를 제공하지 않습니다. 이를 해결하는 한 가지 방법은 Qt에게 QApplication.processEvents()으로 GUI를 업데이트 할 기회를 제공하는 것입니다. 당신은 다음과 같이 logLoop을 수정 그래서 만약 그들이 추가 될 때, 당신은 항목을 볼 수 :

def logLoop(self): 
    for i in range(1000): 
     print i 
     self.addLog("This is a test","c",True) 
     QApplication.processEvents() 

이 어느 정도 유용합니다. processEvents 사이의 시간이 충분히 작 으면 반응 형 UI를 얻을 수 있습니다. 그러나 일이 더 복잡해지고 각 세그먼트에 대한 작업을 완료하는 시간이 길어지면 GUI 응답을 유지하기 위해 코드 조각을 별도의 스레드 (QThread)에 위임해야합니다.

다른 문제는 QListWidget에 많은 수의 항목이 있으면 상황이 느려질 것입니다. 25 번째 항목을 추가하는 것이 925 번째 항목보다 빠르다는 것을 알 수 있습니다. QListWidget (또는 QTableWidget/QTreeWidget)은 확장되지 않기 때문입니다. 많은 수의 항목을 가지려면 모델/뷰 프레임 워크 (QListView/QTableView/QTreeView)를 선택해야합니다.

+0

대단히 감사합니다. 이 정보는 많은 도움이되었지만 각 추가 후에 .setCurrentItem 명령을 사용하면 시간이 크게 달라집니다. 내 응용 프로그램에 대한 요구 사항으로, 나는 목록의 맨 아래에 최신 라인을 가져야하고 항상 최신 라인을 보여야합니다. 내 응용 프로그램은 .3 초마다 줄을 추가하므로 빨리 추가됩니다. 어떤 종류의 이점을 얻으려면 QListView 버전으로 작업을 시작하겠습니다. 다시 한번 감사드립니다. – Stephen

+0

@Stephen : 물론, .setCurrentItem을 사용하면 차이가 생길 것입니다. 결국 _free_가 아니라 오버 헤드가 추가됩니다 :). '0.3 초'당 한 항목은 그렇게 나쁘지 않습니다. 그것은 관리 할 수 ​​있어야합니다. 그러나'QListWidget'의 스케일링 문제는 여전히 존재합니다. 당신은 그것을 관찰 할 수 있습니다. 500 개의 항목을 추가하고 필요한 시간을 측정 한 다음 500 개를 더 추가하십시오. 두 번째는 느려질 것입니다. – Avaris

+0

QTextBrowser와 QTextBrowser.append()를 사용하면 내가 수행하려고 시도한 것에 대한 최상의 결과를 얻었습니다. – Stephen