如何在PyQt中使用按钮退出while循环程序

4

我有以下代码,它将在PyQt中单击“开始”按钮后启动:

def Start(self):
  import time
  import os
  import RPi.GPIO as GPIO
  import datetime

  GPIO.setmode(GPIO.BCM)
  DEBUG = 1

  os.system('clear')

  # SPI port on GPIO
  SPICLK = 18
  SPIMISO = 23
  SPICS = 25

  # set up the SPI interface pins
  GPIO.setup(SPIMISO, GPIO.IN)
  GPIO.setup(SPICLK, GPIO.OUT)
  GPIO.setup(SPICS, GPIO.OUT)

  GPIO.output(SPICS, True)
  GPIO.output(SPICS, False) # bring CS low
  while True:
        adcout = 0             
        read_adc = 0
        #s=time.clock()
        for i in range(25):
            GPIO.output(SPICLK, True)
            GPIO.output(SPICLK, False)
            adcout <<= 1
            if (GPIO.input(SPIMISO)==1):
                adcout |= 0x1
        time.sleep(0.085)   
        if (GPIO.input(SPIMISO)==0):
            read_adc = adcout
            millivolts = read_adc * ( 2500.0 /(pow(2,22)))
            read_adc = "%d" % read_adc
            millivolts = "%d" % millivolts

        if DEBUG:
            print millivolts, "mV (ADC)"

上述程序是用于ADC读取的,它会在点击名为“开始”的按钮后启动,如下所示:self.pushButton.clicked.connect( self.Start) 我还有另一个名为pushButton_2的按钮,称为“停止”,通过单击此按钮,上述进程应该停止。请建议,这样我就可以做到。
2个回答

5

在这个主题上,除了在你的其他问题中所建议的做法之外,不需要做任何事情:只需使用processEvents。只要你可以频繁地调用它(但不要太频繁),它应该会完全符合你的要求。使用你的第二个示例,以下内容对我来说很好用:

  def Start(self):
    if not self.started:
        self.started = True
        self.StartLoop()

  def Stop(self):
    if self.started:
        self.started = False

  def StartLoop(self):
    DEBUG = 1
    while self.started:
        print "LED on "
        time.sleep(0.05)
        print "LED off "
        time.sleep(0.085)
        QtGui.qApp.processEvents()

请注意,我阅读的每篇关于processEvents的文章都警告说,在使用QThread和QTimer方法之后,它应该是最后的选择。不幸的是,我没有找到任何明确的原因,可能是因为它只处理某些类型的事件,并且仅来自调用该函数的线程,所以也许它是那些容易使用但如果它不能正常工作,很难弄清楚原因的函数之一。在OP的情况下,我建议使用QThread。 - Oliver
1
@Schollii。是的,我也遇到了关于processEvents的这种莫名其妙的“挑剔”,好像QThreadQTimer等工具没有它们的局限性(特别是在涉及Python的情况下)。在这个特定的工具箱中有许多工具,没有一个工具能在所有可能的情况下都起作用。所以对我来说,说其中一个应该成为“最后的手段”似乎很愚蠢:相反,应该学会如何使用工具箱中的所有工具,然后选择最适合手头工作的工具。 - ekhumoro
同意,而且一个主要的挑战是学习“最适合手头工作”的标准;我还没有看到过对这三种方法进行清晰比较并考虑每个方面的比较,以确定在特定情况下选择哪种方法。 - Oliver
@Schollii。我想象一下这样的比较(如果彻底进行)可能需要写上好几页…… - ekhumoro

-1
  1. 这个问题很有用:tkinter loop and serial write。可以复制它并进行两个更改:master.update 变成 QtGui.qApp.processEventsmaster.after 变成 QTimer.singleShot

  2. 以下是使用 guiLoop 实现你所要求的草图:

    from guiLoop import guiLoop, stopLoop
    # ... 表示填写你的代码
    class ...: 
        started = False
    
        def Start(self):
            if not self.started:
                # 你也可以在这里使用线程,请参见第一个链接
                self.started = self.StartLoop()
    
        def Stop(self):
            if self.started:
                stopLoop(self.started)
                self.started = False
    
        @guiLoop
        def StartLoop(self):
            # 这是你的开始函数
            # ...
            while True:
                # ...
                yield 0.085 # 等待时间为 0.085 秒
                # ...
    

    由于我不知道你的代码长什么样子,这里提供了一个使用 PyQT4 和 guiLoop 的工作示例:

    from PyQt4 import QtGui
    import sys
    
    from guiLoop import guiLoop # https://gist.github.com/niccokunzmann/8673951
    
    @guiLoop
    def led_blink(argument):
        while 1:
            print("LED on " + argument)
            yield 0.5 # 等待时间
            print("LED off " + argument)
            yield 0.5
    
    app = QtGui.QApplication(sys.argv)
    
    w = QtGui.QWidget()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Simple')
    w.show()
    
    led_blink(w, 'shiny!')
    
    sys.exit(app.exec_())
    

    guiLoop 使用 QTimer.singleShot(time, function) 来使循环继续。

    你也可以使用 guiLoop 的 stopLoop() 来停止循环。


请再看一下问题,我已经添加了一个简单的例子,并且按照您的建议尝试了,但是出了些问题。抱歉,因为我对这些都很新。 - lkkkk
抱歉,请建议我已经编辑了我的问题,即在StartLoop()的最后一个示例中,因为它再次不起作用,我认为是因为循环中有循环。 - lkkkk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接