2017-03-14 8 views
0

서버에서 원격 스크립트를 실행하는 프로그램을 작성했습니다. 그래서 바를 가지고 진행 상황을 보여줄 필요가 있지만 코드를 실행할 때 GUI가 정지하기 시작합니다. QThread와 SIGNAL을 사용했지만 불행하게도 succedeed는 불가능합니다.스레드를 사용한 PyQt 진행률 표시

다음은 아래 코드입니다. 내가 방법을 updateProgressBar보고 기대하고

class dumpThread(QThread): 

    def __init__(self): 
     QThread.__init__(self) 

    def __del__(self): 
     self.wait() 

    def sendEstablismentCommands(self, connection): 

     # Commands are sending sequently with proper delay-timers # 

     connection.sendShell("telnet localhost 21000") 
     time.sleep(0.5) 
     connection.sendShell("admin") 
     time.sleep(0.5) 
     connection.sendShell("admin") 
     time.sleep(0.5) 
     connection.sendShell("cd imdb") 
     time.sleep(0.5) 
     connection.sendShell("dump subscriber") 

     command = input('$ ') 

    def run(self): 
     # your logic here    
     # self.emit(QtCore.SIGNAL('THREAD_VALUE'), maxVal) 
     self.sendEstablismentCommands(connection)  

class progressThread(QThread): 

    def __init__(self): 
     QThread.__init__(self) 

    def __del__(self): 
     self.wait() 


    def run(self): 
     # your logic here 
     while 1:  
      maxVal = 100 
      self.emit(SIGNAL('PROGRESS'), maxVal) 

class Main(QtGui.QMainWindow): 
    def __init__(self): 
     QtGui.QMainWindow.__init__(self) 
     self.ui = Ui_MainWindow() 
     self.ui.setupUi(self) 
     self.ui.connectButton.clicked.connect(self.connectToSESM) 



    def connectToSESM(self): 
     ## Function called when pressing connect button, input are being taken from edit boxes. ## 
     ## dumpThread() method has been designed for working thread seperate from GUI. ## 

     # Connection data are taken from "Edit Boxes" 
     # username has been set as hardcoded 

     ### Values Should Be Defined As Global ### 
     username = "ntappadm" 
     password = self.ui.passwordEdit.text() 
     ipAddress = self.ui.ipEdit.text() 

     # Connection has been established through paramiko shell library 
     global connection 

     connection = pr.ssh(ipAddress, username, password) 
     connection.openShell() 
     pyqtRemoveInputHook() # For remove unnecessary items from console 

     global get_thread 

     get_thread = dumpThread() # Run thread - Dump Subscriber 
     self.progress_thread = progressThread() 

     self.progress_thread.start() 
     self.connect(self.progress_thread, SIGNAL('PROGRESS'), self.updateProgressBar) 

     get_thread.start()  




    def updateProgressBar(self, maxVal): 

     for i in range(maxVal): 
      self.ui.progressBar.setValue(self.ui.progressBar.value() + 1) 
      time.sleep(1) 
      maxVal = maxVal - 1 

      if maxVal == 0: 
       self.ui.progressBar.setValue(100) 

    def parseSubscriberList(self): 
     parsing = reParser() 

    def done(self): 
     QtGui.QMessageBox.information(self, "Done!", "Done fetching posts!") 




if __name__ == "__main__": 
    app = QtGui.QApplication(sys.argv) 
    main = Main() 
    main.show() 
    sys.exit(app.exec_()) 

는 신호라고, 그래서 과정은 별도의 스레드를 통과했다. 나는 실종 된 곳을 찾는다. 어떤 도움

+0

어떻게 신호 정수를 정의 할 수 있습니다와 같은 진행률 표시 줄을 작성하는 더 나은 것입니까? 당신은 eloborate 수 있습니다 : progress_update = QtCore.Signal (int)? – nuriselcuk

+0

1.'progressThread'의 목적은 무엇입니까? 당신은 워커 쓰레드가 있고 그에 따라 당신의 GUI를 업데이트하고 싶어서 제 3의 쓰레드의 필요성을 보지 못했습니다. 2. 왜 당신은'updateProgressBar'에 루프를 가지고 있습니까? 그리고 왜 각 반복 동안'maxVal'을 줄입니까? 그리고 왜 거기에 '시간 잠들기'가 있니? 물론 잠을 자면 메인 스레드가 멈 춥니 다. 또한'updateProgressBar'에 대한 각각의 호출은'maxVal'가 마지막 반복을 위해 0이기 때문에'self.ui.progressBar.setValue (100)'을 끝낼 것입니다. –

답변

1

에 대한

덕분에 정말 두 가지 문제가 있습니다. 필자가 알아챈 한 가지는 직렬 포트에서 읽는 것과 같은 IO 작업에 파이썬 스레드가 사용되지 않는다면 욕심이 많다는 것입니다. 쓰레드에게 IO와 관련이없는 계산이나 무언가를 실행하라고 말하면, 쓰레드는 모든 프로세싱을 수행하고 메인 쓰레드/이벤트 루프가 실행되는 것을 좋아하지 않습니다. 두 번째 문제는 신호가 느리고 ... 매우 느립니다. 나는 당신이 스레드로부터 신호를 내보내고 그것을 매우 빠르게하면 프로그램을 크게 늦출 수 있다는 것을 알았다.

그래서 문제의 핵심은 스레드가 항상 시간을 들이고 매우 느리게 신호를 내보내고 있기 때문에 속도가 느려집니다.

명료성과 사용 편의성을 위해 새로운 스타일의 신호와 슬롯을 사용했습니다. http://pyqt.sourceforge.net/Docs/PyQt4/new_style_signals_slots.html

class progressThread(QThread): 

    progress_update = QtCore.Signal(int) # or pyqtSignal(int) 

    def __init__(self): 
     QThread.__init__(self) 

    def __del__(self): 
     self.wait() 


    def run(self): 
     # your logic here 
     while 1:  
      maxVal = 100 
      self.progress_update.emit(maxVal) # self.emit(SIGNAL('PROGRESS'), maxVal) 
      # Tell the thread to sleep for 1 second and let other things run 
      time.sleep(1) 

는 새로운 스타일 신호

... 
self.progress_thread.start() 
self.process_thread.progress_update.connect(self.updateProgressBar) # self.connect(self.progress_thread, SIGNAL('PROGRESS'), self.updateProgressBar) 
... 

편집 죄송 또 다른 문제가에 연결합니다. 신호가 함수를 호출하면 그 함수에 영원히 머물 수 없습니다. 이 함수는 메인 이벤트 루프에서 실행중인 별도의 스레드에서 실행되지 않고, 메인 이벤트 루프는 해당 함수를 종료 할 때까지 실행 대기합니다.

업데이트 진행률이 1 초 동안 유지되고 반복됩니다. 교수형은이 기능에 머무르는 것으로부터옵니다.

def updateProgressBar(self, maxVal): 

    for i in range(maxVal): 
     self.ui.progressBar.setValue(self.ui.progressBar.value() + 1) 
     time.sleep(1) 
     maxVal = maxVal - 1 

     if maxVal == 0: 
      self.ui.progressBar.setValue(100) 

class progressThread(QThread): 

    progress_update = QtCore.Signal(int) # or pyqtSignal(int) 

    def __init__(self): 
     QThread.__init__(self) 

    def __del__(self): 
     self.wait() 


    def run(self): 
     # your logic here 
     while 1:  
      maxVal = 1 # NOTE THIS CHANGED to 1 since updateProgressBar was updating the value by 1 every time 
      self.progress_update.emit(maxVal) # self.emit(SIGNAL('PROGRESS'), maxVal) 
      # Tell the thread to sleep for 1 second and let other things run 
      time.sleep(1) 


def updateProgressBar(self, maxVal): 
    self.ui.progressBar.setValue(self.ui.progressBar.value() + maxVal) 
    if maxVal == 0: 
     self.ui.progressBar.setValue(100) 
+0

답장을 보내 주셔서 감사합니다.하지만 제 Gui는 여전히 동결 상태입니다. 변화가없는 것처럼 보입니다. 그런데 pyqtSignal (int) – nuriselcuk

+0

을 사용하여 내 대답을 편집하고 updateProgressBar에 머무르는 것에 대한 정보를 너무 오랫동안 추가했습니다. – HashSplat

+0

네, 맞습니다. 코드는 progressBarUpdate에서 for 루프를 끝내기를 기다리고 있습니다. 나는 지금 그것이 작동하고 있다고 갱신했다. 모두에게 감사드립니다. – nuriselcuk