Schleife mit button beginnen u. beenden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Kira
User
Beiträge: 8
Registriert: Freitag 8. Februar 2019, 16:06

Hallo wollte mir für meinen schrittmotor ein GUI Programm mit pyqt schreiben nun habe ich aber ein problem mit dem automatischen drehen Wie kann ich eine schleife in einer funktion starten und beim Loslassen des buttons die schleife wieder beenden ???
Habe schon einiges versucht jedoch ohne erfolg programm kann soweit auch ausprobiert werden Habe es mit kommentaren beschrieben wo sich die problemstellen befinden

Code: Alles auswählen

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'C:\Users\Kira\Desktop\mainwindow.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets
import time
#import RPi.GPIO as GPIO

#GPIO.setmode(GPIO.BOARD)
#GPIO.setwarnings(False)

#GPIO.setup(36,GPIO.OUT)
#GPIO.setup(38,GPIO.OUT)
#GPIO.setup(40,GPIO.OUT)


#GPIO.output(36,GPIO.LOW)
#GPIO.output(38,GPIO.LOW)
#GPIO.output(40,GPIO.LOW)

#a=0
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(733, 581)
        self.centralWidget = QtWidgets.QWidget(MainWindow)
        self.centralWidget.setObjectName("centralWidget")

        self.pushButton = QtWidgets.QPushButton(self.centralWidget)
        self.pushButton.setGeometry(QtCore.QRect(100, 100, 75, 23))
        self.pushButton.setObjectName("pushButton")
        self.pushButton.pressed.connect(self.Links)
        self.pushButton.released.connect(self.Links_aus)

        self.lcdNumber = QtWidgets.QLCDNumber(self.centralWidget)
        self.lcdNumber.setGeometry(QtCore.QRect(150, 20, 101, 41))
        self.lcdNumber.setObjectName("lcdNumber")

        self.pushButton_2 = QtWidgets.QPushButton(self.centralWidget)
        self.pushButton_2.setGeometry(QtCore.QRect(200, 100, 75, 23))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_2.pressed.connect(self.Rechts)
        self.pushButton_2.released.connect(self.Rechts_aus)
        
        self.label = QtWidgets.QLabel(self.centralWidget)
        self.label.setGeometry(QtCore.QRect(70, 30, 51, 16))
        self.label.setObjectName("label")

        self.pushButton_3 = QtWidgets.QPushButton(self.centralWidget)
        self.pushButton_3.setGeometry(QtCore.QRect(270, 30, 75, 23))
        self.pushButton_3.setObjectName("pushButton_3")

        self.label_2 = QtWidgets.QLabel(self.centralWidget)
        self.label_2.setGeometry(QtCore.QRect(150, 200, 61, 16))
        self.label_2.setObjectName("label_2")

        self.spinBox = QtWidgets.QSpinBox(self.centralWidget)
        self.spinBox.setGeometry(QtCore.QRect(90, 250, 91, 22))
        self.spinBox.setObjectName("spinBox")

        self.radioButton = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton.setGeometry(QtCore.QRect(100, 300, 82, 17))
        self.radioButton.setObjectName("radioButton")

        self.radioButton_2 = QtWidgets.QRadioButton(self.centralWidget)
        self.radioButton_2.setGeometry(QtCore.QRect(210, 300, 82, 17))
        self.radioButton_2.setObjectName("radioButton_2")

        self.pushButton_4 = QtWidgets.QPushButton(self.centralWidget)
        self.pushButton_4.setGeometry(QtCore.QRect(140, 340, 75, 23))
        self.pushButton_4.setObjectName("pushButton_4")

        self.doubleSpinBox = QtWidgets.QDoubleSpinBox(self.centralWidget)
        self.doubleSpinBox.setGeometry(QtCore.QRect(210, 250, 62, 22))
        self.doubleSpinBox.setMinimum(0.0)
        self.doubleSpinBox.setMaximum(999.99)

        self.doubleSpinBox.setObjectName("doubleSpinBox")
        self.label_3 = QtWidgets.QLabel(self.centralWidget)
        self.label_3.setGeometry(QtCore.QRect(110, 230, 47, 13))
        self.label_3.setObjectName("label_3")

        self.label_4 = QtWidgets.QLabel(self.centralWidget)
        self.label_4.setGeometry(QtCore.QRect(200, 230, 91, 16))
        self.label_4.setObjectName("label_4")

        self.label_5 = QtWidgets.QLabel(self.centralWidget)
        self.label_5.setGeometry(QtCore.QRect(170, 80, 47, 13))
        self.label_5.setObjectName("label_5")

        self.label_6 = QtWidgets.QLabel(self.centralWidget)
        self.label_6.setGeometry(QtCore.QRect(160, 130, 47, 13))
        self.label_6.setObjectName("label_6")

      
      


      #Hier befindet sich der button um den es sich handelt


        self.pushButton_5 = QtWidgets.QPushButton(self.centralWidget)
        self.pushButton_5.setGeometry(QtCore.QRect(100, 150, 75, 23))
        self.pushButton_5.setObjectName("pushButton_5")
        self.pushButton_5.pressed.connect(self.Button_auto_Links_an)
        self.pushButton_5.released.connect(self.Button_auto_Links_aus)

        self.pushButton_6 = QtWidgets.QPushButton(self.centralWidget)
        self.pushButton_6.setGeometry(QtCore.QRect(200, 150, 75, 23))
        self.pushButton_6.setObjectName("pushButton_6")

        MainWindow.setCentralWidget(self.centralWidget)

        self.menuBar = QtWidgets.QMenuBar(MainWindow)
        self.menuBar.setGeometry(QtCore.QRect(0, 0, 733, 21))
        self.menuBar.setObjectName("menuBar")

        MainWindow.setMenuBar(self.menuBar)

        self.mainToolBar = QtWidgets.QToolBar(MainWindow)
        self.mainToolBar.setObjectName("mainToolBar")

        MainWindow.addToolBar(QtCore.Qt.TopToolBarArea, self.mainToolBar)
        self.statusBar = QtWidgets.QStatusBar(MainWindow)
        self.statusBar.setObjectName("statusBar")

        MainWindow.setStatusBar(self.statusBar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "Links"))
        self.pushButton_2.setText(_translate("MainWindow", "Rechts"))
        self.label.setText(_translate("MainWindow", "Schrittzahl"))
        self.pushButton_3.setText(_translate("MainWindow", "Reset"))
        self.label_2.setText(_translate("MainWindow", "Automatik"))
        self.radioButton.setText(_translate("MainWindow", "Links"))
        self.radioButton_2.setText(_translate("MainWindow", "Rechts"))
        self.pushButton_4.setText(_translate("MainWindow", "Start"))
        self.label_3.setText(_translate("MainWindow", "Schrittzahl"))
        self.label_4.setText(_translate("MainWindow", "Geschwindigkeit in"))
        self.label_5.setText(_translate("MainWindow", "1 Schritt"))
        self.label_6.setText(_translate("MainWindow", "Dauerhaft"))
        self.pushButton_5.setText(_translate("MainWindow", "Links"))
        self.pushButton_6.setText(_translate("MainWindow", "Rechts"))




    def Links(self):
        print("Links")
    
        #GPIO.output(36, GPIO.HIGH)
        #GPIO.output(38, GPIO.HIGH)
        #GPIO.output(40, GPIO.LOW)

    def Links_aus(self):
        print ("Links")
        #GPIO.output(36, GPIO.LOW)
        #GPIO.output(38, GPIO.HIGH)
        #GPIO.output(40, GPIO.HIGH)

    def Rechts(self):
        print("Rechts")
    
        #GPIO.output(36, GPIO.HIGH)
        #GPIO.output(38, GPIO.LOW)
        #GPIO.output(40, GPIO.LOW)

    def Rechts_aus(self):
        print("Rechts_Aus")
        #GPIO.output(36, GPIO.LOW)
        #GPIO.output(38, GPIO.LOW)
        #GPIO.output(40, GPIO.HIGH)
        
        
        
        
# Hier die schleife um die es sich handelt

    def Button_auto_Links_an(self):
        #global a
        #a=1
        Links_Auto(self,1)

    def Button_auto_Links_aus(self):
        #global a
        #a=0
        Links_Auto(self,0)

    def Links_Auto(a):
        counter = 0
        a=True
        print("Links")

        while 0 < a:
            #GPIO.output(36, GPIO.LOW)
            #GPIO.output(38, GPIO.HIGH)
            #GPIO.output(40, GPIO.HIGH)
            time.sleep(0.1)
            #GPIO.output(40, GPIO.LOW)
            counter = counter + 1
            print(counter)
            time.sleep(0.1)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Blockierender Code und GUIs sind natuerliche Todfeinde. GUIs leben davon, dass die ganze Zeit auf Ereignisse reagiert werden kann - Benutzereingaben, Daten- und Timer-Evens.

Und letztere sind auch dein Freund - du musst mit QTimern arbeiten, um deine Ansteuerung vorzunehmen. Allerdings ist dein Vorgehen da eh fragwuerdig - das Betriebssystem garantiert einem nicht, dass ein time.sleep wirklich genau so lange schlaeft, wie der Benutzer angegeben hat. Das fuehrt dann dazu, dass deine Motoren stottern.

Besser ist es also entweder in smartere Treiber zu investieren, oder deine Ansteuerung mit dem eh deutlich ueberlegenen pigpio vorzunehemen. Da kannst du mit dem Wave-Chain-Feature hochstabile Pulse generieren lassen, die dann nur noch durch deine Buttons parametrisiert werden.
Sirius3
User
Beiträge: 17746
Registriert: Sonntag 21. Oktober 2012, 17:20

@Kira: zu dem, was __deets__ schon geschrieben hat, die Warnung im Kommentar sagt doch deutlich, dass man die generierten Dateien nicht editieren sollte. Eigentlich erzeugt man gar keine py-Dateien sonder lädt direkt die .ui-Datei.

Was die auskommentierten Zeilen betrifft. GPIO-Warnungen sind dazu da, dass man sie behebt und nicht, dass man sie ignoriert. Daher fehlt am Schluß auch ein cleanup.

`global` hat in einem richtigen Programm nichts verloren, vor allem nicht, wenn sie `a` heißen. Warum willst Du 0 mit True vergleichen?
Kira
User
Beiträge: 8
Registriert: Freitag 8. Februar 2019, 16:06

Das heißt jetzt das ich die ui Datei allein arbeiten lasse und das Programm in einer anderen klasse ab arbeiten lasse der gpio Fehler kommt nur auf dem Rechner und nicht auf dem raspberry deshalb musste ich ihn rausnehmen und global wahr nur ein versuch suche einfach nur eine Möglichkeit die schleife mit einem button zu zu beenden programmiere noch nicht so lange mit python habe eher Erfahrung mit sps Programmierung wo man mit 0 und 1 hantieren kann
Kira
User
Beiträge: 8
Registriert: Freitag 8. Februar 2019, 16:06

Hätte den vllt mal jemand ein bsp für mich weil jedes mal drum herum reden wie es nicht geht nützt mir nix
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Kira: Gibt's auf Deiner Tastatur keine Satzzeichen? Das liest sich nicht wirklich gut/flüssig, wenn man selbst heraus finden muss wo ein Satz aufhört und der nächste anfängt…

Wo hast Du denn jetzt konkret ein Problem?

Mit Warnungen ausschalten war übrigens diese Zeile gemeint: ``#GPIO.setwarnings(False)``. Das solltest Du nicht machen, sondern dafür sorgen das am Programmende die `GPIO.cleanup()`-Funktion aufgerufen wird. Das Du das nicht machst ist nämlich der Grund warum Du Warnungen bekommst.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Kira
User
Beiträge: 8
Registriert: Freitag 8. Februar 2019, 16:06

Mit den gpio hab ich gar keine Probleme. Ich würde einfach nur gerne wissen, wie ich beim betätigen eines buttons eine Endlosschleife starte und sie beim loslassen des Buttons wieder beende. Die Endlosschleife soll dann später nur mein Taktgeber für meinen Schrittmotor sein.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Hast du gelesen, was ich die dazu geschrieben habe? https://github.com/pootle/pisteppers Ist ein Projekt, dass das wie von mir beschrieben macht. Das kannst du einbauen oder per socket fernsteuern.
Kira
User
Beiträge: 8
Registriert: Freitag 8. Februar 2019, 16:06

Oh ja die Seite sieht gut aus danke werde dort mal etwas rum Stöbern. Würde trotzdem mal gerne wissen wie ich eine schleife in einer Funktion mit einem Button stoppen kann. Dann währe mir sehr geholfen
Sirius3
User
Beiträge: 17746
Registriert: Sonntag 21. Oktober 2012, 17:20

@Kira: nochmal, das geht gar nicht, weil es keine Schleifen in einem GUI-Programm geben darf, die ewig laufen.
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es. Geht. Nicht. Eine solche Schleife blockiert die Ausfuehrung des GUI-mainloops. Und wenn der nicht ausgefuehrt wird, dann erkennt die GUI auch nicht, wenn ein Knopf gedrueckt wird.

Man muss die Arbeit also auf kleine Schnipsel aufteilen, welche nur kurz laufen. ZB mit Timern. Das habe ich dir aber schon erklaert. Hast du nach den dir gegebenen Begriffen mal gesucht, und versucht zu verstehen, was das ist?
Kira
User
Beiträge: 8
Registriert: Freitag 8. Februar 2019, 16:06

OK ich denke ich habe es jetzt erst mal begriffen. Ja hab mir die Seite und die Begriffe mal angeschaut muss mich erst mal damit beschäftigen da ich noch nicht so lange mit Python Arbeite. Jetzt noch mal für mich als Anfänger ich habe eine Klasse für die GUI und alles andere Programmrelevante befindet sich dann auserhalb der GUI Klasse in z.B anderen Klassen u. Funktionen ?
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das waere eine sinnvolle Aufteilung, ja. Wobei das von mir gezeigte Projekt ja sogar als eigenstaendiges Programm arbeitet. Ob es out-of-the-box funktioniert haengt jetzt ein bisschen von deinem Motor-Treiber ab.

Und die Art, wie man mit ui-Dateien arbeitet ist anders, als du sie benutzt hast. Du hast aus der .ui-Datei ein Python-File erzeugt, und das modifiziert. Und wenn du jetzt im Designer etwas re-arrangierst, oder gar Dinge hinzufuegst oder entfernst - was machst du dann? Da deine Aenderungen von Hand nachzupflegen ist nicht nur anstrengend, sondern vor allem fehleranfaellig.

Wie man das normalerweise macht siehst du hier: https://github.com/antoskape/lf-manager ... ger.py#L25
Kira
User
Beiträge: 8
Registriert: Freitag 8. Februar 2019, 16:06

So ich glaube ich habe es jetzt erst mal geschaft, habe jetzt 2 Programme eines für die GUI und eins für das eigentliche Programm. Beide kummunizieren jetzt über ein Textdokument welches Ständig von der GUI beschrieben (je nach welche Eingabe gerade gemacht wird) und von dem Programm ausgelessen wird. Somit weiß das Programm welche Aktion ausgeführt werden soll oder die Schleife gestartet oder gestopt werden soll.
Benutzeravatar
__blackjack__
User
Beiträge: 13100
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Kira: Kann man machen, aber schön ist anders. Und man sollte natürlich sicherstellen, das das schreiben/lesen der Textdatei atomar geschieht und da nicht ein Programm eine erst teilweise geschriebene Datei ausliest.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
__deets__
User
Beiträge: 14533
Registriert: Mittwoch 14. Oktober 2015, 14:29

Statt eines Textdokumentes kannst du auch einen "named pipe" bzw. fifo benutzen.
Sirius3
User
Beiträge: 17746
Registriert: Sonntag 21. Oktober 2012, 17:20

... oder Sockets, wenn man es bidirektional haben will.
Kira
User
Beiträge: 8
Registriert: Freitag 8. Februar 2019, 16:06

Ich kann mir vorstellen dass das nicht die schönste art ist aber sie funktioniert erst mal mit dem wenigsten aufwand. Da ich noch Programmierneuling bin taste ich mich erst mal heran was funktioniert u. was nicht. _deet_ hat mir zwar auch gute beispiele gezeigt aber da muss ich mich erst mal hinein fuchsen. Wenn ich mal fragen darf könntest ihr mir vllt mal an einem kleinem bsp zeigen wie ihr das Problem gelöst hättet ob mit Klasse oder mit 2 Programmen GUI Könntet ihr ja meine benutzen würde mich mal interessieren für Lehrnzwecke.
Antworten