2017-11-29 3 views
0

나는 프로젝트를위한 GUI를 만들기 위해 PyQt를 사용하고있다. 숫자를 입력하고 제출 후 PyQt5 : 백그라운드에서 기능 실행 및 UI 업데이트

GUI

스크린 샷, 나는 프로세스가 완료 될 때까지 다른 응용 프로그램은 동결, 배경에서 실행됩니다 기능을 실행해야합니다.

또한 함수에 의해 생성 된 어두운 상자에 로그를 출력해야합니다.

import sys 
from PyQt5.QtWidgets import (
    QWidget, 
    QDesktopWidget, 
    QLineEdit, 
    QGridLayout, 
    QLabel, 
    QFrame, 
    QPushButton, 
    QApplication, 
    QTextEdit 
) 
from PyQt5.QtGui import (QTextCursor) 
from bot.bot import (run, slack_notification) 
from multiprocessing import Process, Pipe 

class LogginOutput(QTextEdit): 
    def __init__(self, parent=None): 
     super(LogginOutput, self).__init__(parent) 

     self.setReadOnly(True) 
     self.setLineWrapMode(self.NoWrap) 

     self.insertPlainText("") 

    def append(self, text): 
     self.moveCursor(QTextCursor.End) 
     current = self.toPlainText() 

     if current == "": 
      self.insertPlainText(text) 
     else: 
      self.insertPlainText("\n" + text) 

     sb = self.verticalScrollBar() 
     sb.setValue(sb.maximum()) 

class App(QWidget): 
    def __init__(self): 
     super().__init__() 

     self.init_ui() 

    def init_ui(self): 
     label = QLabel('Amount') 
     amount_input = QLineEdit() 
     submit = QPushButton('Submit', self) 
     box = LogginOutput(self) 

     submit.clicked.connect(lambda: self.changeLabel(box, amount_input)) 

     grid = QGridLayout() 
     grid.addWidget(label, 0, 0) 
     grid.addWidget(amount_input, 1, 0) 
     grid.addWidget(submit, 1, 1) 
     grid.addWidget(box, 2, 0, 5, 2) 

     self.setLayout(grid) 
     self.resize(350, 250) 
     self.setWindowTitle('GetMeStuff Bot v0.1') 
     self.show() 

    def center(self): 
     qr = self.frameGeometry() 
     cp = QDesktopWidget().availableGeometry().center() 
     qr.moveCenter(cp) 
     self.move(qr.topLeft()) 

    def changeLabel(self, box, user_input): 
     p = Process(target=run, args=(user_input.displayText(), box)) 
     p.start() 
     user_input.clear() 


if __name__ == '__main__': 
    app = QApplication(sys.argv) 
    widget = App() 
    sys.exit(app.exec_()) 

그리고 run 기능 :

은 GUI 코드

백그라운드에서 기능을 실행하기 위해
def run(user_input, log): 
    if user_input == "": 
     log.append("Please enter a value\n") 
    else: 
     log.append("Test") 

, 내가 Process를 사용하는 것을 시도했다, 그러나 나는 실행할 때 이 추가되면 GUI가 업데이트되지 않습니다.

사전

+0

귀하의 코드 만이을 구축하는 방법을 보여줍니다 전체와 가능한 예를 들어 다음 코드에

class LogginOutput(QTextEdit): [...] @pyqtSlot(str) def append(self, text): self.moveCursor(QTextCursor.End) [...] 

:이를 위해 우리는 장식을 사용, 제대로이 슬롯해야 호출하려면 GUI, 당신이 언급 한 주된 문제는 아무것도 나타내지 않고 프로세스에 대해 이야기하고 당신이 그것을 어떻게 사용하는지 보여주지 않습니다. 우리가 당신을 돕기를 원한다면 [mvce]를 제공해야합니다. – eyllanesc

+0

죄송합니다. 설명이 충분하다고 생각했습니다. 임무 코드가 추가되었습니다. – user7391037

답변

0

파이썬은 스레드로 작업하는 많은 대안을 제공하지만 Qt는 응용 프로그램이 살아있는 루프를 생성하므로 GUI를 다른 스레드에서 업데이트하면 안됩니다. 종종 이러한 도구는 Qt의 논리를 처리하지 못하기 때문에 문제가 발생할 수 있습니다. Qt는 QThread (낮은 수준)와 작업의 유형을 수행하는 클래스를 제공합니다,하지만 난 QRunnable 및 QThreadPool를 사용하는이 시간, 나는 프로세스와 동일하게 동작하는 클래스 만들었습니다

class ProcessRunnable(QRunnable): 
    def __init__(self, target, args): 
     QRunnable.__init__(self) 
     self.t = target 
     self.args = args 

    def run(self): 
     self.t(*self.args) 

    def start(self): 
     QThreadPool.globalInstance().start(self) 

사용 :

self.p = ProcessRunnable(target=run, args=(user_input.displayText(), box)) 
self.p.start() 

또한 나는 해결책은 신호를 사용하거나이 경우, 간단하게하기 위해 사용하는 것입니다 당신이 다른 스레드에서 직접 GUI를 업데이트하지 말아야 전에 말했듯이 QMetaObject.invokeMethod :

def run(user_input, log): 
    text = "" 
    if user_input == "": 
     text = "Please enter a value\n" 
    else: 
     text = "Test" 

    QMetaObject.invokeMethod(log, 
       "append", Qt.QueuedConnection, 
       Q_ARG(str, text)) 
import sys 
from PyQt5.QtWidgets import * 
from PyQt5.QtGui import * 
from PyQt5.QtCore import * 

class ProcessRunnable(QRunnable): 
    def __init__(self, target, args): 
     QRunnable.__init__(self) 
     self.t = target 
     self.args = args 

    def run(self): 
     self.t(*self.args) 

    def start(self): 
     QThreadPool.globalInstance().start(self) 

def run(user_input, log): 
    text = "" 
    if user_input == "": 
     text = "Please enter a value\n" 
    else: 
     text = "Test" 

    QMetaObject.invokeMethod(log, 
       "append", Qt.QueuedConnection, 
       Q_ARG(str, text)) 

class LogginOutput(QTextEdit): 
    def __init__(self, parent=None): 
     super(LogginOutput, self).__init__(parent) 

     self.setReadOnly(True) 
     self.setLineWrapMode(self.NoWrap) 
     self.insertPlainText("") 

    @pyqtSlot(str) 
    def append(self, text): 
     self.moveCursor(QTextCursor.End) 
     current = self.toPlainText() 

     if current == "": 
      self.insertPlainText(text) 
     else: 
      self.insertPlainText("\n" + text) 

     sb = self.verticalScrollBar() 
     sb.setValue(sb.maximum()) 

class App(QWidget): 
    def __init__(self): 
     super().__init__() 

     self.init_ui() 

    def init_ui(self): 
     label = QLabel('Amount') 
     amount_input = QLineEdit() 
     submit = QPushButton('Submit', self) 
     box = LogginOutput(self) 

     submit.clicked.connect(lambda: self.changeLabel(box, amount_input)) 

     grid = QGridLayout() 
     grid.addWidget(label, 0, 0) 
     grid.addWidget(amount_input, 1, 0) 
     grid.addWidget(submit, 1, 1) 
     grid.addWidget(box, 2, 0, 5, 2) 

     self.setLayout(grid) 
     self.resize(350, 250) 
     self.setWindowTitle('GetMeStuff Bot v0.1') 
     self.show() 

    def center(self): 
     qr = self.frameGeometry() 
     cp = QDesktopWidget().availableGeometry().center() 
     qr.moveCenter(cp) 
     self.move(qr.topLeft()) 

    def changeLabel(self, box, user_input): 
     self.p = ProcessRunnable(target=run, args=(user_input.displayText(), box)) 
     self.p.start() 
     user_input.clear() 


if __name__ == '__main__': 
    app = QApplication(sys.argv) 
    widget = App() 
    sys.exit(app.exec_()) 
0

에 감사 당신은 하나의 스레드 또는 프로세스에 갈 수 있다는 점에서 바로 그래서 그것이 자신의 차단 루프의 항상 필요합니다 GUI를 응용 프로그램. 그러나 일단 Qt를 사용하면 제공된 도구를 사용하여 산란해야합니다.

시도 PyQt5.QtCore.QProcess 또는 PyQt5.QtCore.QThread.

나는 당신에게 어울리는 야생의 예를 찾을 수있을 것이라고 확신한다.

관련 문제