2017-12-27 9 views
1

Ich möchte wissen, wie kann ich den Prozess der Funktion iniciarPyqt5 Wie kann man das Programm durch eine unendliche while-Schleife einfrieren?

jedes Mal, wenn ich auf die Schaltfläche self.runButton.clicked.connect(self.iniciar)

das Programm friert klicken stoppen und ich kann eine andere Aktion nicht.

Ich möchte den Timer weiter arbeiten, während die Funktion iniciar wiederholt unendlich wiederholt.

auch, dass die Schaltfläche self.runButton1 die Funktion iniciar stoppt.

mein Code:

#!/usr/bin/env python3 

# Program created for play audios of time in zapoteco' 
# 
# Created by: Python 3.6, PyQt5 5.9.2. 
# 
# Author: Raul Espinosa [email protected] 
# 
# WARNING! All changes made in this file will be lost! 
# 
# Version 0.2 GUI 

import time 
import subprocess 

from PyQt5 import QtCore, QtGui, QtWidgets 

class Ui_Form(object): 
    def setupUi(self, Form): 
     Form.setObjectName("Form") 
     Form.resize(383, 263) 
     palette = QtGui.QPalette() 
     brush = QtGui.QBrush(QtGui.QColor(164, 0, 0)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Button, brush) 
     brush = QtGui.QBrush(QtGui.QColor(138, 226, 52)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Light, brush) 
     brush = QtGui.QBrush(QtGui.QColor(164, 0, 0)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Text, brush) 
     brush = QtGui.QBrush(QtGui.QColor(173, 127, 168)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush) 
     brush = QtGui.QBrush(QtGui.QColor(114, 159, 207)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush) 
     brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Shadow, brush) 
     brush = QtGui.QBrush(QtGui.QColor(164, 0, 0)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Button, brush) 
     brush = QtGui.QBrush(QtGui.QColor(138, 226, 52)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Light, brush) 
     brush = QtGui.QBrush(QtGui.QColor(164, 0, 0)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Text, brush) 
     brush = QtGui.QBrush(QtGui.QColor(173, 127, 168)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush) 
     brush = QtGui.QBrush(QtGui.QColor(114, 159, 207)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush) 
     brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Shadow, brush) 
     brush = QtGui.QBrush(QtGui.QColor(46, 52, 54)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Button, brush) 
     brush = QtGui.QBrush(QtGui.QColor(138, 226, 52)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Light, brush) 
     brush = QtGui.QBrush(QtGui.QColor(190, 190, 190)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Text, brush) 
     brush = QtGui.QBrush(QtGui.QColor(114, 159, 207)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush) 
     brush = QtGui.QBrush(QtGui.QColor(114, 159, 207)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush) 
     brush = QtGui.QBrush(QtGui.QColor(0, 0, 0)) 
     brush.setStyle(QtCore.Qt.SolidPattern) 
     palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Shadow, brush) 
     Form.setPalette(palette) 
     Form.setPalette(palette) 
     self.label = QtWidgets.QLabel(Form) 
     self.label.setGeometry(QtCore.QRect(10, 0, 361, 181)) 
     self.label.setObjectName("label") 
     self.horizontalSlider = QtWidgets.QSlider(Form) 
     self.horizontalSlider.setGeometry(QtCore.QRect(110, 240, 160, 16)) 
     self.horizontalSlider.setOrientation(QtCore.Qt.Horizontal) 
     self.horizontalSlider.setObjectName("horizontalSlider") 
     self.horizontalSlider.setRange(0,100) 
     self.horizontalSlider.setSingleStep(1) 
     self.horizontalSlider.valueChanged.connect(self.valueHandler) 
     self.runButton = QtWidgets.QPushButton(Form) 
     self.runButton.setGeometry(QtCore.QRect(50, 180, 80, 25)) 
     self.runButton.setObjectName("runButton") 
     self.runButton.clicked.connect(self.iniciar) 
     self.runButton1 = QtWidgets.QPushButton(Form) 
     self.runButton1.setGeometry(QtCore.QRect(250, 180, 80, 25)) 
     self.runButton1.setObjectName("runButton1") 
     self.label_2 = QtWidgets.QLabel(Form) 
     self.label_2.setGeometry(QtCore.QRect(160, 220, 55, 17)) 
     self.label_2.setObjectName("label_2") 
     self.timer = QtCore.QTimer(Form) 
     self.timer.timeout.connect(self.Time) 
     self.timer.start(1000) 
     self.lcdNumber = QtWidgets.QLCDNumber(Form) 
     self.lcdNumber.setGeometry(QtCore.QRect(280, 0, 101, 61)) 
     self.lcdNumber.setInputMethodHints(QtCore.Qt.ImhNone) 
     self.lcdNumber.setFrameShape(QtWidgets.QFrame.NoFrame) 
     self.lcdNumber.setFrameShadow(QtWidgets.QFrame.Raised) 
     self.lcdNumber.setSmallDecimalPoint(True) 
     self.lcdNumber.setDigitCount(5) 
     self.lcdNumber.setMode(QtWidgets.QLCDNumber.Dec) 
     self.lcdNumber.setSegmentStyle(QtWidgets.QLCDNumber.Flat) 
     self.lcdNumber.display(time.strftime("%H"+":"+"%M")) 
     #tiempo = time.strftime("%H"+":"+"%M") 
     #print (tiempo) 
     #self.lcdNumber.setProperty("value", 12:20) 
     self.lcdNumber.setObjectName("lcdNumber") 
     self.retranslateUi(Form) 
     QtCore.QMetaObject.connectSlotsByName(Form) 

    def Time(self): 
     self.lcdNumber.display(time.strftime("%H"+":"+"%M")) 

    def valueHandler(self,value): 
     scaledValue = float(value)/100 
     print (scaledValue) , type(scaledValue) 
     return scaledValue 

    def retranslateUi(self, Form): 
     _translate = QtCore.QCoreApplication.translate 
     Form.setWindowTitle(_translate("Form", "XIGABA")) 
     Form.setToolTip(_translate("Form", "<html><head/><body><pre style=\" margin-top:0px; margin-bottom:15px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#ffffff;\"><span style=\" font-family:\'monospace\'; background-color:#ffffff;\">Creado con Software Libre.</span></pre></body></html>")) 
     self.label.setToolTip(_translate("Form", "<html><head/><body><p>Dictador de horario.</p></body></html>")) 
     self.label.setText(_translate("Form", "<html><head/><body><pre align=\"center\" style=\" margin-top:15px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#729fcf;\"><a name=\"taag_output_text\"/><span style=\" font-family:\'monospace\'; color:#555753; background-color:#729fcf;\">)</span><span style=\" font-family:\'monospace\'; color:#555753; background-color:#729fcf;\"> (        </span></pre><pre align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#729fcf;\"><span style=\" font-family:\'monospace\'; color:#555753; background-color:#729fcf;\"> (/()\\) (  (  ( (  </span></pre><pre align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#729fcf;\"><span style=\" font-family:\'monospace\'; color:#555753; background-color:#729fcf;\">)\\()|()/()\\) )\\ ()\\ )\\  </span></pre><pre align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#729fcf;\"><span style=\" font-family:\'monospace\'; color:#555753; background-color:#729fcf;\">((_)\\ /(_)|()/(((((_)()((_|(((_)( </span></pre><pre align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#729fcf;\"><span style=\" font-family:\'monospace\'; color:#555753; background-color:#729fcf;\">__((_|_)) /(_))_)\\ _)((_)_)\\ _)\\ </span></pre><pre align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#729fcf;\"><span style=\" font-family:\'monospace\'; color:#555753; background-color:#729fcf;\">\\ \\/ /_ _|(_)) __(_)_\\(_) _)(_)_\\(_) </span></pre><pre align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#729fcf;\"><span style=\" font-family:\'monospace\'; color:#555753; background-color:#729fcf;\"> &gt; &lt; | | | (_ |/ _ \\ | _ \\/_ \\ </span></pre><pre align=\"center\" style=\" margin-top:0px; margin-bottom:15px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#729fcf;\"><span style=\" font-family:\'monospace\'; color:#555753; background-color:#729fcf;\">/_/\\_\\___| \\___/_/ \\_\\|___//_/ \\_\\ </span></pre><pre align=\"center\" style=\" margin-top:0px; margin-bottom:15px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#729fcf;\"><span style=\" font-family:\'monospace\'; font-size:6pt; color:#555753; background-color:#729fcf;\">version 0.2 GUI</span></pre></body></html>")) 
     self.runButton.setText(_translate("Form", "Iniciar")) 
     self.runButton1.setText(_translate("Form", "Detener")) 
     self.label_2.setText(_translate("Form", "<html><head/><body><pre align=\"center\" style=\" margin-top:0px; margin-bottom:15px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; background-color:#000000;\"><a name=\"taag_output_text\"/><span style=\" font-family:\'monospace\'; color:#ef2929; background-color:#000000;\">VOLUMEN</span></pre></body></html>")) 

    def iniciar(self): 
     self.runButton1.setEnabled(True) 
     position = self.horizontalSlider.value() 
     scaledValue = float(position)/100 
     print (scaledValue) , type(scaledValue) 

     while (True): 
      time.sleep(0.5) 
      second_test = time.strftime('%S') 
      minute_test = time.strftime('%M') 
      hour_test = time.strftime('%H') 
      tiempo = time.strftime("%H"+":"+"%M") 
      print (tiempo) 
      self.lcdNumber.setProperty("value", tiempo) 
      if int(minute_test) == int(00) and int(second_test) == int(00): 
       print ('llego al hora exacta') 
       filen = 'HRS' + hour_test + '_O.mp3.mp3' 
       print (filen) 
       subprocess.Popen(["play", filen, "vol", scaledValue]).communicate() 
      elif int(second_test) == int(00): 
       print ('llego al minuto') 
       filen = 'HRS' + hour_test + '.mp3' 
       filen2 = 'MIN' + minute_test + '.mp3.mp3' 
       print (filen) 
       print (filen2) 
       subprocess.Popen(["play", filen, "vol", str(scaledValue)]).communicate() 
       subprocess.Popen(["play", filen2, "vol", str(scaledValue)]).communicate() 

if __name__ == "__main__": 
    import sys 
    app = QtWidgets.QApplication(sys.argv) 
    Form = QtWidgets.QWidget() 
    ui = Ui_Form() 
    ui.setupUi(Form) 
    Form.show() 
    sys.exit(app.exec_()) 

Ich bin es gewohnt, python3.6 und pyqt5

+0

von dem, was ich Ihre Methode kann sagen, 'iniciar' die meiste Zeit schlafen verbringen und wird, Blockieren Sie daher die Ereignisschleife "Qt". Ein besserer Weg zu gehen, könnte sein, [QTimer'] (http://doc.qt.io/qt-5/qtimer.html) für Timing-Ereignisse und ['QProcess'] (http: // doc .qt.io/qt-5/qprocess.html) für die Prozessausführung/Kontrolle. Auf diese Weise können Sie den Signal/Slot-Mechanismus von 'Qt' nutzen, um die Ereignisschleife nicht zu blockieren. –

Antwort

1

Blocking Schleifen wie die während wahr, dass Sie verwenden, sind für eine GUI nicht geeignet, weil sie lassen Sie nicht die typische tun Aufgaben einer GUI wie das Überprüfen von Ereignissen, Signalen und Slots.

In Qt, und daher auch PyQt, gibt es Methoden, um diese Probleme zu vermeiden, eine mögliche Lösung für Ihren Fall ist die Verwendung von Threads, und eine einfache Möglichkeit, sie zu implementieren, ist QRunnable und QThreadPool, aber vorher ist es ratsam um deinen Code zu reformieren.

Qt Designer bietet eine Klasse, die ein Design in Widget implementieren kann, aber es ist kein Widget, es ist angemessen, eine Klasse zu erstellen, die vom entsprechenden Widget erbt und die anfängliche Klasse zum Füllen verwendet.

class Widget(QtWidgets.QWidget, Ui_Form): 
    def __init__(self, *args, **kwargs): 
     QtWidgets.QWidget.__init__(self, *args, **kwargs) 
     self.setupUi(self) 
     self.runButton.clicked.connect(self.iniciar) 
     self.timer.timeout.connect(self.update_time) 
     self.horizontalSlider.valueChanged.connect(self.valueHandler) 

    def update_time(self): 
     self.lcdNumber.display(time.strftime("%H" + ":" + "%M")) 

    def valueHandler(self, value): 
     scaledValue = float(value)/100 
     print(scaledValue), type(scaledValue) 
     return scaledValue 

    def iniciar(self): 
     self.runButton1.setEnabled(True) 
     position = self.horizontalSlider.value() 
     scaledValue = float(position)/100 
     print(scaledValue), type(scaledValue) 
     self.runnable = Runnable(self) 
     QtCore.QThreadPool.globalInstance().start(self.runnable) 

Im nächsten Abschnitt implementieren ich die QRunnable und wir geben das Widget, wird dieses Widget der GUI-Daten zu kommunizieren und aktualisieren verwendet werden, da in der Regel von Qt ist, dass die GUI soll nicht von einem anderen Thread aktualisiert werden eine Lösung hierfür ist die Verwendung QMetaObject.invokeMethod:

class Runnable(QtCore.QRunnable): 
    def __init__(self, w, *args, **kwargs): 
     QtCore.QRunnable.__init__(self, *args, **kwargs) 
     self.w = w 
     self.position_initial = self.w.horizontalSlider.value() 

    def run(self): 
     scaledValue = float(self.position_initial)/100 

     print(scaledValue) 
     while True: 
      time.sleep(0.5) 
      second_test = time.strftime('%S') 
      minute_test = time.strftime('%M') 
      hour_test = time.strftime('%H') 
      tiempo = time.strftime("%H" + ":" + "%M") 
      print(tiempo) 
      QtCore.QMetaObject.invokeMethod(self.w.lcdNumber, "display", 
              QtCore.Qt.QueuedConnection, 
              QtCore.Q_ARG(str, tiempo)) 
      if int(minute_test) == int(00) and int(second_test) == int(00): 
       print('llego al hora exacta') 
       filen = 'HRS' + hour_test + '_O.mp3.mp3' 
       print(filen) 
       subprocess.Popen(["play", filen, "vol", scaledValue]).communicate() 
      elif int(second_test) == int(00): 
       print('llego al minuto') 
       filen = 'HRS' + hour_test + '.mp3' 
       filen2 = 'MIN' + minute_test + '.mp3.mp3' 
       print(filen) 
       print(filen2) 
       subprocess.Popen(["play", filen, "vol", str(scaledValue)]).communicate() 
       subprocess.Popen(["play", filen2, "vol", str(scaledValue)]).communicate() 

Dann wird, wie implementiert, in der iniciar Methode, rufen wir die runnable durch QThreadPool:

self.runnable = Runnable(self) 
QtCore.QThreadPool.globalInstance().start(self.runnable) 

Den vollständigen Code finden Sie unter link.

PS:

Wenn Sie wollen ein Ende fügen wir einige Dinge zum Beispiel ändern müssen statt while True sollten Sie eine Flagge verwenden, und den Zustand der Flagge ändern:

class Runnable(QtCore.QRunnable): 
    def __init__(self, w, *args, **kwargs): 
     QtCore.QRunnable.__init__(self, *args, **kwargs) 
     self.w = w 
     self.position_initial = self.w.horizontalSlider.value() 
     self.m_stopped = False 

    def run(self): 
     scaledValue = float(self.position_initial)/100 

     print(scaledValue) 
     while not self.m_stopped: 
      [...] 

    def stop(self): 
     self.m_stopped = True 

und dann haben wir die detener Methode:

def detener(self): 
    self.runButton.setEnabled(True) 
    self.runButton1.setEnabled(False) 
    self.runnable.stop() 
+0

danke funktioniert gut! Ich bin add 'self.runButton1.clicked.connect (self.detener) 'und' fuction def detener (Selbst-): \t self.runButton.setEnabled (True) \t self.runButton1.setEnabled (False) \t self.runnable = Runnable (Selbst-) \t QtCore.QThreadPool.globalInstance () .stop (self.runable) 'aber gibt es keinen Halt? – laur

+0

Wenn Sie die Dokumentation überprüft haben, sehen Sie, dass QThreadPool keine Stopp-Methode hat. In wenigen Augenblicken werde ich Ihnen zeigen, wie Sie die Ausführung stoppen können: – eyllanesc

+0

danke @eyllanesc – laur

Verwandte Themen