Seite 1 von 1

Wertänderungen eines Sliders registrieren und auswerten

Verfasst: Freitag 25. Februar 2022, 23:42
von pippsen
Hallo,

habe mit Qt/Pyside6 versucht mir einen Slider zu programmieren und den Wert für eine "If Abfrage" zu benutzen. Leider komme ich aber im "Loop" nicht wirklich an diese Variable, bzw. wird der "loop" nicht ausgeführt solange die GUI läuft.

Anbei der Code:

Code: Alles auswählen

from PySide6.QtWidgets import QApplication, QWidget,QHBoxLayout, QLabel, QSlider
import sys
from PySide6.QtGui import QIcon
from PySide6.QtCore import Qt
from PySide6 import QtGui

value = 0

class Window(QWidget):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Pyside2 Slider")
        self.setGeometry(300,200,300,250)
        self.setStyleSheet('background-color:red')
        self.createSlider()
        self.setIcon()
        self.show()

    def setIcon(self):
        appIcon = QIcon("icon.png")
        self.setWindowIcon(appIcon)

    def createSlider(self):
        hbox = QHBoxLayout()

        self.slider = QSlider()
        self.slider.setOrientation(Qt.Horizontal)
        self.slider.setTickPosition(QSlider.TicksBelow)
        self.slider.setTickInterval(10)
        self.slider.setMinimum(0)
        self.slider.setMaximum(100)

        self.slider.valueChanged.connect(self.changedValue)

        self.label = QLabel("0")
        self.label.setFont(QtGui.QFont("Sanserif", 15))

        hbox.addWidget(self.slider)
        hbox.addWidget(self.label)

        self.setLayout(hbox)

    def changedValue(self):
        size = self.slider.value()
        self.label.setText(str(size))
        


myapp = QApplication(sys.argv)
window = Window()
myapp.exec()
sys.exit()

while True:
    value = window.slider.value()
    
    if value <= 50:
        print('Wert unter 50')
    elif value > 50:
        print('Wert über 50')
Danke für Eure Hilfe!

Re: Wertänderungen eines Sliders registrieren und auswerten

Verfasst: Samstag 26. Februar 2022, 00:23
von __blackjack__
@pippsen: So funktioniert GUI-Programmierung nicht. Wenn die GUI-Hauptschleife läuft kann Deine Schleife nicht laufen. Und wenn eine Schleife von Dir läuft, wird die GUI nicht aktualisiert und reagiert auch nicht auf den Benutzer.

Du hast da ja bereits eine Methode die aufgerufen wird, wenn sich der Wert ändert. Dort muss dann auch das passieren was Du in der Schleife stehen hast. Ohne Schleife.

Das einerseits QtGui importiert und `QFont` darüber erreicht wird, andererseits `QIcon` direkt importiert wird, ist inkonsequent. Wonach wurde denn diese Entscheidung getroffen?

Auf Modulebene sollte nur Code stehen, der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Die Vorsilbe `my` bei Namen macht in 99,99% der Fälle keinen Sinn weil sie keine Information transportiert. Es sei denn es gäbe auch eine `our_app` oder `their_app` oder so, um `my_app` davon abzugrenzen.

Der `show()`-Aufruf gehört nicht in die `__init__()`. Das macht kein vorhandenes Fenster/Widget selbst.

Die Aufteilung der `__init__()` auf mehrere Methoden macht keinen Sinn.

Das `valueChanged`-Signal sendet einen `int`-Wert für den Dein Slot kein Argument vorsieht.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import sys

from PySide6.QtCore import Qt
from PySide6.QtGui import QIcon, QFont
from PySide6.QtWidgets import (
    QApplication,
    QHBoxLayout,
    QLabel,
    QSlider,
    QWidget,
)


class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Pyside2 Slider")
        self.setGeometry(300, 200, 300, 250)
        self.setStyleSheet("background-color:red")
        self.setWindowIcon(QIcon("icon.png"))

        hbox = QHBoxLayout()

        self.slider = QSlider()
        self.slider.setOrientation(Qt.Horizontal)
        self.slider.setTickPosition(QSlider.TicksBelow)
        self.slider.setTickInterval(10)
        self.slider.setMinimum(0)
        self.slider.setMaximum(100)

        self.slider.valueChanged.connect(self.onValueChanged)

        self.label = QLabel(str(self.slider.value()))
        self.label.setFont(QFont("Sanserif", 15))

        hbox.addWidget(self.slider)
        hbox.addWidget(self.label)

        self.setLayout(hbox)

    def onValueChanged(self, value):
        self.label.setText(str(value))
        if value <= 50:
            print("Wert kleiner oder gleich 50")
        else:
            print("Wert grösser 50")


def main():
    app = QApplication(sys.argv)
    window = Window()
    window.show()
    sys.exit(app.exec())


if __name__ == "__main__":
    main()

Re: Wertänderungen eines Sliders registrieren und auswerten

Verfasst: Samstag 26. Februar 2022, 15:47
von pippsen
Hallo __blackjack__,

vielen Dank für deine prompte Antwort und deine Hinweise zu dem Code. Zu meiner Entschuldigung muss ich gestehen das ich aus der Welt der EN 61131 (Codesys/Twincat3) im strukturierten Text komme und dort mehr Erfahrung habe. Dort kann ich aus meiner GUI Variablen zum weiterverarbeiten nehmen ohne auf die Verarbeitung zu achten. Hier laufen GUI und "Programm" parallel.
Du hast da ja bereits eine Methode die aufgerufen wird, wenn sich der Wert ändert. Dort muss dann auch das passieren was Du in der Schleife stehen hast. Ohne Schleife.
Das es in der Methode funktioniert, ist mir bewusst. Ich wollte nur den Wert außerhalb der GUI weiterverarbeiten.
Das einerseits QtGui importiert und `QFont` darüber erreicht wird, andererseits `QIcon` direkt importiert wird, ist inkonsequent. Wonach wurde denn diese Entscheidung getroffen?

Auf Modulebene sollte nur Code stehen, der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Die Vorsilbe `my` bei Namen macht in 99,99% der Fälle keinen Sinn weil sie keine Information transportiert. Es sei denn es gäbe auch eine `our_app` oder `their_app` oder so, um `my_app` davon abzugrenzen.

Der `show()`-Aufruf gehört nicht in die `__init__()`. Das macht kein vorhandenes Fenster/Widget selbst.

Die Aufteilung der `__init__()` auf mehrere Methoden macht keinen Sinn.

Das `valueChanged`-Signal sendet einen `int`-Wert für den Dein Slot kein Argument vorsieht.
Diesen Code habe ich aus einem YouTube Tutorial und habe nicht hinterfragt wie etwas importiert, benahmt oder aufgeteilt wurde. Auch wenn es sicherlich nicht die beste Grundlage gewesen ist, hat diese zumindest für das Beispiel funktioniert.

Was ich eigentlich damit vorhabe ist:

Ich habe ein laufendes Script, welches mit mit Python und OpenCV Farbe detektiert. Um gewisse Schwellwerte einzustellen habe ich bis dato die Möglichkeit der Slider von OpenCV benutzt. Mit dieses stoße ich aber schnell an die Grenzen. Nun dachte ich mir das ich nun einfach eine GUI implementiere, wo ich die Verarbeitung besser steuern kann, Variablen auslese und diese aber auch in die GUI wieder zurückschreibe. Hier wären es Filterwerte für RGB bzw HSV.

Wäre hier "threading" der richtige weg, so das GUI und Hauptprogramm "parallel" ablaufen?

Besten Dank

Re: Wertänderungen eines Sliders registrieren und auswerten

Verfasst: Samstag 26. Februar 2022, 17:52
von __deets__
Die GUI ist immer das Hauptprogramm. Das ist technisch so festgelegt. Aber du kannst einen Arbeitsthread starten, ja. Wichtig hierbei aber: du darfst NICHT einfach aus dem anderen Thread auf die GUI-Elemente zugreifen! Das kann zu boesen, harten Abstueren fuehren. Wenn du einen QThread benutzt, dann kann der per queued connection den Slider-Value an den Thread senden. Oder du packst das in eine Variable/Eigenschaft, die der Arbeitsthread einliest.

Re: Wertänderungen eines Sliders registrieren und auswerten

Verfasst: Sonntag 27. Februar 2022, 13:16
von pippsen
Vielen Dank für die Hinweise und Hilfestellung! Ich denke es hat mir den Weg gezeigt, welchen ich nun versuche zu gehen.

Gruß