Seite 1 von 2

PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Sonntag 22. März 2015, 17:41
von smile-1969
Hallo,
versuche leider erfolglos meine "items" der Combobox in mein Programm einzubinden.
Beschreibung des Programms: Mit den Pushbuttons "EIN" und "AUS" schalte ich eine definierte LED1 ein bzw. aus.
Über eine Combobox möchte ich nun eine Auswahl zur Verfügung stellen, welche Led geschaltet werden soll (LED1, LED2 oder...).
Wie verbinde ich nun die jeweils ausgewählte LED der Combobox mit dem entsprechenden Programmablauf?
Müsste doch auf diese Art funktionieren: if...Inhalt Combobox=LED1...schalte LED1...etc.
Habe mich zwar durch etwaige Dokumentationen gekämpft, finde aber leider nicht das passende oder verstehe es einfach nicht.
Vielleicht kann mir jemand mit einem verständlichem Beispiel helfen?
Danke Uwe

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Sonntag 22. März 2015, 18:06
von Hyperion
Du kannst eine ComboBox auf verschiedene Art und Weise verwenden. Lies Dir doch mal die Doku dazu durch.

Eine einfache (und für Dich vermutlich hinreichende) Möglichkeit wäre es, über den Namen zu gehen. Also wählt jemand den Eintrag "LED3" aus, so kannst Du in einem Dict nachgucken, welcher Port o.ä. zu dieser LED gehört.

Dazu müssten wir aber erst wissen, wie Deine Datenstrukturen so aussehen.

Sind die LEDs durchnummeriert, wäre das Arbeiten über den Index auch denkbar.

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Sonntag 22. März 2015, 19:04
von Madmartigan
Eine Möglichkeit ist, die LEDs in einem Dictionary vorrätig zu halten, als Keys verwendest du fortlaufende Ganzzahlen.
Dann kannst du den currentIndex der QComboBox als Index des Dictionary benutzen.

Auch interessant dazu: currentIndexChanged

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Sonntag 22. März 2015, 19:16
von smile-1969
Wenn ich das richtig verstehe, dann ist diese Zuordnung als im Dict hinterlegt, also wie genau erstelle ich den?
Habe die Combobox über QtDesigner mit den den aufeinanderfolgenden Zeilen LED1, LED2...gefüllt, lade die die ui., kann in der Box auswählen, habe aber keine Verbindung zu einer Aktion. Hoffe das beantwortet die Frage zu meiner Datenstruktur...

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Sonntag 22. März 2015, 19:33
von Hyperion
Madmartigan hat geschrieben:Eine Möglichkeit ist, die LEDs in einem Dictionary vorrätig zu halten, als Keys verwendest du fortlaufende Ganzzahlen.
Bei *fortlaufenden* Ganzzahlen ist ein Dictionary nicht unbedingt das beste Mittel. Da reicht dann ja eine Liste vollkommen aus, ggf. auch eine Liste von Tupeln mit dem Aufbau (name, led_port) o.ä.

@smile-1996: Öh... das ist jetzt nicht unbedingt der beste Weg. Somit hast Du ja Daten und GUI ziemlich stark verzahnt. Und von eine explizite Struktur hast Du jetzt ja gar nicht, sondern die Daten sind in der UI-Datei fix hinterlegt.

Fangen wir mal anders an: Soll die Bezeichnung denn so simpel bleiben? Und Was passiert denn konkret, wenn man die LED1 auswählt? Und was bei LED2 und LED3 usw.? Was sind die speziellen Daten, die dann zum Zuge kommen?

Wenn wir das wissen, kann man Dir auch raten, wie Du am besten vorgehst!

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Sonntag 22. März 2015, 19:51
von Madmartigan
Hyperion hat geschrieben:
Madmartigan hat geschrieben:Eine Möglichkeit ist, die LEDs in einem Dictionary vorrätig zu halten, als Keys verwendest du fortlaufende Ganzzahlen.
Bei *fortlaufenden* Ganzzahlen ist ein Dictionary nicht unbedingt das beste Mittel. Da reicht dann ja eine Liste vollkommen aus, ggf. auch eine Liste von Tupeln mit dem Aufbau (name, led_port) o.ä.
Das Dictionary ermöglich ihm aber die Auswahl der LEDs per Namen. Die Liste ist da nicht die erste Wahl, sie hätte keinen Vorteil.

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Sonntag 22. März 2015, 19:53
von Sirius3
@Madmartigan: Du schreibst selbst von einem *Index*. Auf Listen wird per Index zugegriffen, auf Dictionaries per Key. Also wo ist hier der Vorteil eines Wörterbuchs? Nein, die offensichtliche Datenstruktur ist eine Liste.

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Sonntag 22. März 2015, 20:02
von smile-1969
Über die die beiden PushButtons der Gui kann ich eine Led ein-bzw. ausschalten. Wird also der Button "EIN" betätigt, wird die Routine buttonEIN aufgerufen und GPIO-Port 4 auf High gesetzt bzw. über die Routine buttonAUS auf LOW, wenn der Button "Aus" geklickt wird. Das funktioniert auch. Nun möchte ich das Programm wie folgt erweitern:
Über die Combobox möchte ich einstellen, welche Led bzw. welcher GPIO-Port angesprochen werden soll. Ist also in der Combobox LED1 ausgewählt, soll entsprechend der GPIO-Port 4 geschaltet werden. Ist LED2 gewählt, soll der GPIO-Port 18 geschaltet werden usw. Entsprechend der Auswahl der Combobox soll also eine zugeordnete Routine aufgerufen werden.
Nachtrag: Habe das offensichtliche vergessen, steuer über die GUI die Ports eines RPi.

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Montag 23. März 2015, 08:59
von Hyperion
Dann hast Du mehrere Möglichkeiten:

1.) Du speicherst Dir die Ports in einer Liste oder Tupel in der Reihenfolge der Buttons, also nach Deiner Beschreibung etwa so:

Code: Alles auswählen

LED_PORTS = (4, 18, ...)
Damit kannst Du über den aktuellen Index der ComboBox an den korrespondierenden Port gelangen, indem Du mit diesem Index auf Deine Liste zugreifst.

2.) Wenn Du Namen oder Reihenfolge variieren willst, kannst Du auch eine Tupelstruktur wählen, und diese als Grundlage sowohl für die Einträge in der ComboBox als auch für das Vermerken der Ports nutzen:

Code: Alles auswählen

LED_PORTS = (
    ("LED1", 4),
    ("LED hinten links", 18),
    ...
)
Die Box kannst Du nun befüllen, indem Du über die Tupel iterierst und den ersten Eintrag jedes Tupels per ``AddItem`` oder so ähnlich setzt. (Also *nicht* per Designer schon die Einträge da reinpackst!)
Die Auswahl kann analog zu Lösung 1 erfolgen, also per ``currentIndex``.

Sollten die Namen wirklich immer gleich fortlaufend sein, also "LED1", "LED2", usw., so bietet es sich auch bei Lösung 1 an, diese im Programm zu generieren und zwar basierend auf der definierten Liste. Damit stellst Du sicher, dass es nie eine Option in der Combobox gibt, zu der *kein* index in der Liste existiert!
Dies kannst Du einfach über die ``enumerate``-Funktion oder ein ``range(len(...))``-Konstrukt erreichen.

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Montag 23. März 2015, 09:19
von Madmartigan
Sirius3 hat geschrieben:@Madmartigan: Du schreibst selbst von einem *Index*. Auf Listen wird per Index zugegriffen, auf Dictionaries per Key.
Du wirst recht haben, die Bezeichnung des Keys als Index bei Verwendung von Ganzzahlen ist natürlich sträflich falsch.
Sirius3 hat geschrieben:Also wo ist hier der Vorteil eines Wörterbuchs?
Das hatte ich bereits beschrieben. :roll:
Sirius3 hat geschrieben:Nein, die offensichtliche Datenstruktur ist eine Liste.
Du kennst den Satz vielleicht: Yeah, well, that's just, like, your opinion, man.

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Montag 23. März 2015, 10:04
von Hyperion
@Madmartigan: Ja, wenn man per Name auf die LED zugreifen will. Ein Dictionary hat aber zunächst den Nachteil, dass es unsortiert ist, d.h. man beim Einfügen in die ComboBox die Schlüssel noch sortieren oder ein ``OrderedDict`` nutzen müsste. Wenn dazu keine Notwendigkeiot besteht, erhöht das ganze lediglich die Komplexität - und hier sehe ich bisher keine Notwendigkeit. Der OP hat von Datenstrukturen vermutlich eh noch nicht so viel Ahnung, da sind die von mir beschriebenen Ansätzer zudem sicherlich einfacher für ihn.

Und bei einem Zugriff auf eine Datenstruktur mit fortlaufenden Nummern würde ich ein Dictionary definitiv als suboptimal ansehen, da es nur Overhead aber keinen Vorteil gegenüber einer Liste bietet.

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Montag 23. März 2015, 11:17
von jerch
Die Diskussion Liste vs. Wörterbuch ist für den OP wahrscheinlich sophistisch. Zum Glück hat Python nur zwei Standardcontainer und nicht die Phalanx an Containern wie C++ mit den stl::Containertypen. Da lässt sich sich wirklich trefflich drüber streiten ;)

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Montag 23. März 2015, 15:08
von smile-1969
Also, habe jetzt erstmal versucht die items im Programm einzufügen und nicht im QtDesigner direkt. Leider bekomme ich dabei folgende Fehlermeldung im Terminal angezeigt:

(gksudo:3253): GLib-CRITICAL **: g_str_has_prefix: assertion 'str != NULL' failed

Habe meinen Code mal angehängt, damit wird es vielleicht einfacher für euch.

Code: Alles auswählen

#! /usr/bin/env/python
# -*- coding: utf-8 -*-

import sys
from PyQt4.QtCore import*
from PyQt4.QtGui import*
from PyQt4.uic import*
import RPi.GPIO as GPIO     

GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(18, GPIO.OUT)
GPIO.setup(24, GPIO.OUT)

def buttonEin():
       
    GPIO.output(4, 1)

def buttonAus():

    GPIO.output(4, 0)   


app = QApplication(sys.argv)
w = loadUi("ue-control.ui")

w.connect(w.buttonAUF, SIGNAL("clicked()"), buttonEin)
w.connect(w.buttonZu, SIGNAL("clicked()"), buttonAus)


combo = QTGui.QCombobox(self)

items = ('LED1', 'LED2')
combo.addItems(items)

w.show()
sys.exit(app.exec_())

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Montag 23. März 2015, 15:24
von BlackJack
@smile-1969: Das wird vom Programm ``gksudo`` ausgegeben. Ich sehe jetzt nicht was das mit Deinem Code zu tun haben soll.

Dein Programm müsste aber eine Fehlerausgabe liefern weil `QTGui` undefiniert ist. `self` wird auch nirgends definiert. Wenn Du die Combobox per Code erstellst, musst Du die auch irgendwo in die angezeigte GUI einbauen. Ich würde die aber nicht per Code erzeugen sondern im QtDesigner.

Durch die Sternchenimporte kann man nicht mehr nachvollziehen was eigentlich aus welchem Modul kommt. Das sollte man deswegen so nicht machen sondern die Namen die man verwendet explizit importieren oder über das jeweilige importierte Modul ansprechen.

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Montag 23. März 2015, 15:52
von smile-1969
O.k., dann belasse ich das erstmal bei der im QtDesigner erstellten Variante. Komme ich momentan eh besser klar mit.
Was den Rest angeht muss ich mich dann morgen nochmal step für step durcharbeiten/durchfragen, bin heute etwas knapp an Zeit.
Danke erstmal,

Gruß Uwe

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Montag 23. März 2015, 17:08
von Hyperion
smile-1969 hat geschrieben:O.k., dann belasse ich das erstmal bei der im QtDesigner erstellten Variante. Komme ich momentan eh besser klar mit.
Es ging auch nicht um das *Erstellen* der ComboBox, sondern um das *Befüllen* mit Werten ;-)

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Dienstag 24. März 2015, 12:17
von BlackJack
Komplett ungetestet:

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
import sys
from functools import partial

from PyQt4.QtGui import QApplication
from PyQt4.uic import loadUi
from RPi import GPIO

LED_PINS = [4, 18, 24]


class LedUI(object):
    def __init__(self, led_pins):
        self.led_pins = led_pins
        for pin in self.led_pins:
            GPIO.setup(pin, GPIO.OUT)
        self.ui = loadUi('ue-control.ui')
        self.ui.ledCombo.addItems(
            ['LED{0}'.format(i + 1) for i in range(len(self.led_pins))]
        )
        self.ui.buttonAUF.clicked.connect(partial(self.on_led_button, True))
        self.ui.buttonZU.clicked.connect(partial(self.on_led_button, False))
        self.ui.show()

    def on_led_button(self, state):
        index = self.ui.ledCombo.currentIndex()
        if index != -1:
            GPIO.output(self.led_pins[index], state)


def main():
    GPIO.setmode(GPIO.BCM)
    application = QApplication(sys.argv)
    led_ui = LedUI(LED_PINS)
    sys.exit(application.exec_())


if __name__ == '__main__':
    main()

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Dienstag 24. März 2015, 14:57
von smile-1969
Tja also erstmal Danke für deine Mühe! Leider erhalte ich damit jetzt wieder diese ominöse "gksudo"-Fehlermeldung. Da ich nur über gksudo gleichzeitig auf die Ports + GUI Zugriff habe, weiß ich gerade nicht woran es hapert!? Irgendwelche Ideen?

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Dienstag 24. März 2015, 15:07
von BlackJack
Wie spielt denn gksudo da überhaupt rein? Was startest Du denn damit und wo erscheint diese Meldung? Normalerweise startet man das ja über den ”Launcher” und hat damit gar keine Ausgaben von dem Programm in irgendeinem Terminal.

Re: PyQt4 ComboBox-item mit einer Funktion verbinden

Verfasst: Dienstag 24. März 2015, 15:32
von smile-1969
Starte das Programm über Putty im Terminal. Wenn ich es allerdings über die Remotedesktopverbindung starte, kommt die Fehlermeldung:AttributeError: 'QMainwindow' object has no attribute 'led combo'
Ich kann zumindest mein Programm nur via gksudo vom Terminal starten, da ich nicht als 'root' auf den Rpi zugreife. Also muss ich aus dem Terminal via gksudo die root-Rechte erteilen. Anders kriege ich kein Programm mit Zugriff auf die Ports zum Laufen.