【问题标题】:Break an infinit loop when button is pressed按下按钮时中断无限循环
【发布时间】:2020-01-24 14:16:04
【问题描述】:

我目前开始使用 PyQt5 并创建了我的第一个 GUI。现在我想要一个执行以下操作的程序。当按下按钮“开始”时,执行 n 次“功能”直到按下按钮“停止”(想象一个秒表),如果我再次按下按钮“开始”,“功能”将再次执行,依此类推。

到目前为止,我尝试的是以下内容,但无法正常工作,因为我们无法从循环外部更改变量(模拟脚本)

class Ui(QtWidgets.QDialog):
def __init__(self):
    super(Ui, self).__init__()
    uic.loadUi('interfaceScan.ui', self)
    self.startScan = self.findChild(QtWidgets.QPushButton, 'startScan') 
    self.startScan.clicked.connect(self.startPressed)

    self.pauseScan = self.findChild(QtWidgets.QPushButton, 'pauseScan')
    self.pauseScan.clicked.connect(self.pausePressed) 

    self.show()

    def startPressed(self):
            global pauseScan
            pauseScan = False 
            dosomething()

    def pausePressed(self):
            global pauseScan
            pausScan = True

def dosomething(): 
    while pauseScan == False: #not needed, but the measurement should be executed periodically until 'pause' is pressed
        print('Running') #in the reals program the measurement will be executed here 
        time.sleep(4) #between each measurement the program needs to wait a cirtain amount of time ~1h  

app = QtWidgets.QApplication(sys.argv)
window = Ui()
app.exec_()

关于如何解决这个问题的任何想法?我现在相对确定它在使用 while 循环时不起作用,所以我愿意接受有关如何更改它的建议!

此脚本的目的是控制一个测量设置,该设置应该运行 1000 个周期,但我希望能够在其间中断以更改参数。

【问题讨论】:

  • 您的dosomething 函数需要在不同的线程中执行,以便界面本身在dosomething 执行时保持响应(即当您按下“停止”时能够做出反应)。这个话题比你的平均 SO 答案要复杂一些,所以我建议阅读这个introduction to multithreading in PyQt
  • time.sleep(4) 是延迟还是模拟耗时的任务?
  • @123einhundert 我建议您放置您的真实代码,因为您似乎无法树立一个好榜样,因为取决于您真正在做什么,一个或可以提出另一种解决方案。
  • @123einhundert 我们需要一个好的 MRE,但根据您的示例,我们不知道代码的哪一部分是可修改的,哪一部分是不可修改的。例如,我可以消除 while 循环并休眠吗?
  • @123einhundert 这些库我们(至少不是我)不感兴趣,因为它没有给我们任何信息,我想要的是正确理解你的代码,也就是说,哪一部分是强制性的,哪个部分是可修改的,如果您使用 while 循环 + sleep,您可以使用它定期执行任务,因此在这种情况下最好使用 QTimer。相反,如果您有消耗超过 10 毫秒的任务,则有必要在另一个线程中执行它......

标签: python loops pyqt5


【解决方案1】:

正如 OP 在 cmets 中指出的那样,带有 time.sleep() 的 while 循环仅旨在执行周期性任务,但这会产生问题,因为 time.sleep() 会冻结 GUI,而必须使用 QTimer使用:

from PyQt5 import QtCore, QtWidgets, uic


class Ui(QtWidgets.QDialog):
    def __init__(self):
        super(Ui, self).__init__()
        uic.loadUi("interfaceScan.ui", self)
        self.startScan.clicked.connect(self.startPressed)
        self.pauseScan.clicked.connect(self.pausePressed)

        self.timer = QtCore.QTimer(self, interval=4 * 1000, timeout=dosomething)

    @QtCore.pyqtSlot()
    def startPressed(self):
        QtCore.QTimer.singleShot(0, dosomething)
        self.timer.start()

    @QtCore.pyqtSlot()
    def pausePressed(self):
        self.timer.stop()


def dosomething():
    print("Running")


if __name__ == "__main__":

    app = QtWidgets.QApplication(sys.argv)
    window = Ui()
    window.show()
    sys.exit(app.exec_())

【讨论】:

    猜你喜欢
    • 2022-01-25
    • 2010-11-03
    • 2022-10-01
    • 2019-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    相关资源
    最近更新 更多