Two (probably) very simple questions
-
Hi Sorren, welcome to Qt!
Glad to see someone else using PyQt on Raspberry Pi ;o) I've gone through and amended your code listing as follows:
@
from PyQt4 import QtCore, QtGuiclass Window(QtGui.QWidget):
def init(self):
super(Window, self).init()self.initUI() def initUI(self): button = QtGui.QPushButton('Toggle LED', self) button.setCheckable(True) button.move(145, 50) self.label = QtGui.QLabel(self) self.label.setText("initializing...") self.label.move(145, 25) button.clicked[bool].connect(self.toggleLED) self.checkLED() self.setGeometry(300,300,280,170) self.setWindowTitle('LED Interface') self.show() def toggleLED(self, pressed): if pressed: GPIO.output(22,1) else: GPIO.output(22,0) def checkLED(self): V1 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS) V2 = readadc(1, SPICLK, SPIMOSI, SPIMISO, SPICS) Vdrop = V1-V2 LED_Status = (Vdrop > 350) and (Vdrop < 450) if LED_Status: text = "The LED is ON" else: text = "The LED is NOT ON" self.label.setText(text)
if name == 'main':
from sys import argv, exitapp = QtGui.QApplication(argv) ex = Window() ex.show() exit(app.exec_())
@
There were a few fundamental issues here to address:
Python code should be indented consistently with exactly 4 spaces (not tabs!)
Your label has to belong to the instance (self) of the Window() that you are creating to be able to reference it (see line 14, self.label)
The reason you couldn't see your window (even with the errors commented out) is because you a) hadn't called show() on your window and, b) becuase you hadn't started an event loop (app.exec_()).
These are just a few fundamental things to do with Python, OO and Qt: once learned never forgotten ;o) There are some really good tutorials out there that will explain these things.
Hope this gets you up and running and good luck and feel free to ask more questions ;o)
-
Thank you so much for your help! I implemented the changes you suggested, and now the window pops up, and pressing the button results the LED turning on or off. However, the label stays the same, reading that the LED is off the whole time. Assuming that my function for checking the LED is correct, is it possible that the function is only called once, at the beginning? Is there a way in which I could call it constantly throughout the program without changing the button's ability to toggle the light?
-
You are absolutely correct, your checkLED() function is only called once when the Window() is created. The following example uses a QTimer that calls your checkLED method once a second:
@
from PyQt4 import QtCore, QtGuiclass Window(QtGui.QWidget):
def init(self):
super(Window, self).init()self.initUI() def initUI(self): l=QtGui.QVBoxLayout(self) button = QtGui.QPushButton('Toggle LED', self) button.setCheckable(True) l.addWidget(button) self.label = QtGui.QLabel(self) self.label.setText("initializing...") l.addWidget(self.label) button.clicked[bool].connect(self.toggleLED) self.timer=QtCore.QTimer(self) self.timer.timeout.connect(self.checkLED) self.timer.start(1000) self.setWindowTitle('LED Interface') self.show() def toggleLED(self, pressed): if pressed: GPIO.output(22,1) else: GPIO.output(22,0) @QtCore.pyqtSlot() def checkLED(self): V1 = readadc(0, SPICLK, SPIMOSI, SPIMISO, SPICS) V2 = readadc(1, SPICLK, SPIMOSI, SPIMISO, SPICS) Vdrop = V1-V2 LED_Status = (Vdrop > 350) and (Vdrop < 450) if LED_Status: text = "The LED is ON" else: text = "The LED is NOT ON" self.label.setText(text)
if name == 'main':
from sys import argv, exitapp = QtGui.QApplication(argv) ex = Window() ex.show() exit(app.exec_())
@
Hope this helps ;o)
-
@jazzycamel Most of the resources online are only discussing pyqt and gpio output(ex: turning a lightbulb on). Has anyone gotten pyqt to work as a GPIO button signalling the computer that the button is pressed as a GPIO input (sorry messed that up previously)? The only information that I have found so far is making a thread (qthread) so looping can be processed separately, but I have not seen an example of this working for GPIO input . An example would be greatly appreciated! Thanks!
-
Something like the following should do what you want (if I'm understanding you correctly):
import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) from functools import partial from PyQt5.QtCore import QObject, pyqtSignal pyqtWrapperType=type(QObject) class Singleton(pyqtWrapperType): _instances={} def __call__(cls, *args, **kwargs): if cls not in cls._instances: cls._instances[cls]=super(Singleton, cls).__call__(*args, **kwargs) return cls._instances[cls] class QGPIO(QObject, metaclass=Singleton): interrupted=pyqtSignal(int,int) @staticmethod def _callback(pin, event): QGPIO().interrupted.emit(pin,event) def register(self, pin, event, bounceTime=300): callback=partial(self._callback, pin, event) GPIO.add_event_detect(pin, event, callback=callback, bouncetime=bounceTime) if __name__=="__main__": from sys import argv, exit from PyQt5.QtCore import pyqtSlot from PyQt5.QtWidgets import QApplication, QWidget class Widget(QWidget): def __init__(self, parent=None, **kwargs): super().__init__(parent, **kwargs) GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP) QGPIO().interrupted.connect(self.interrupted) QGPIO().register(17, GPIO.FALLING) @pyqtSlot(int,int) def interrupted(self, pin, event): print("Interrupted:", pin, event) a=QApplication(argv) w=Widget() w.show() exit(a.exec_())
Basically(!), I create a singleton
QObject()
that has a callback that can be registered with the RPi.GPIO interrupt system such that, when an edge change is detected, theQGPIO()
class will trap the interrupt via_callback
and then emit a signalinterrupted(int,int)
which will inform a slot of which pin has changed and by which event type.Just a warning/disclaimer: I've tested all the PyQt bits, but I had to stub the RPi.GPIO bits as I don't have a Pi handy right this second.
-
@jazzycamel What do I change to make this work for pyqt4? I am currently using a RaspberryPi 0 and it looks like pyqt5 doesnt have full support for arm v6 cpu.
-
@Stumbino
Not much I shouldn't have thought...Change the
PyQt5
imports toPyQt4
and use the Python 2 (I'm assuming you are using Python 2 with PyQt4?) metaclass syntax i.e.:class QGPIO(QObject): __metaclass__=Singleton
Should work fine. I don't have a
PyQt4
setup to test I am afraid, but if you have any issues just post 'em here :) -
@jazzycamel I got all the libraries switched over to pyqt4, but I get these two errors when I run the program.
-
@jazzycamel That worked! How would I load a UI file in the Widget class? I tried using uic.loadUI(), but that seems to override the previous gui.