Sliderwerte aus Funktion exportieren

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Tom Brady
User
Beiträge: 9
Registriert: Freitag 4. Dezember 2015, 07:13

Hallo Leute,
ich habe mir mit dem Q Designer ein kleines MainWindow mit 2 Schiebereglern und 3 LCD-Widgets gebaut.
Die 2 Schieberegler habe ich direkt mit den LCDs verbunden.
Die Werte der Slider werden auch innerhalb der Funktion angezeigt, d.h. ich kann sie "printen"
Nun möchte ich die Werte der ersten beiden LCDs auf das 3. addiert übertragen.
Kann mir jemand sagen, wie ich "p" und "v" aus der Funktion herrausbekomme? Mit RETURN oder GLOBAL scheint es nicht zu funktionieren.

Ich benutze WinPython-64bit-2.7.10.3 auf einem Win 8.1 System.
Vielen Dank

Code: Alles auswählen

import sys
from PyQt4 import QtGui, QtCore
from PyQt4.uic import loadUiType


Ui_MainWindow, QMainWindow = loadUiType('Schiebung.ui')
    
class Main(QMainWindow, Ui_MainWindow):
        def __init__(self):
            super(Main, self).__init__()
            self.setupUi(self)
            
app = QtGui.QApplication(sys.argv)
main = Main()

global p
global v

def prop(p):
    print(p)
    return p

def vol(v):
    print(v)
    return v

x = p + v
print(x)

main.lcdNumber_3.display(int(x))

main.connect(main.horizontalSlider, QtCore.SIGNAL('valueChanged(int)'), prop)
main.connect(main.horizontalSlider_2, QtCore.SIGNAL('sliderMoved(int)'), vol)
main.connect(main.horizontalSlider, QtCore.SIGNAL('sliderMoved(int)'), main.lcdNumber.display)
main.connect(main.horizontalSlider_2, QtCore.SIGNAL('sliderMoved(int)'), main.lcdNumber_2.display)

if __name__ == '__main__':
        main.show()
sys.exit(app.exec_())
Zuletzt geändert von cofi am Freitag 4. Dezember 2015, 09:18, insgesamt 1-mal geändert.
Grund: Code Highlighting korrigiert
BlackJack

@Tom Brady: Davon abgesehen das ``global`` auf Modulebene keinerlei Wirkung hat, vergiss bitte das es ``global`` überhaupt gibt. Das hier löst man über Objektorientierung. Die braucht man und sollte man verstanden haben bevor man mit GUI-Programmierung anfänft. Insbesondere bei einem komplexen objektorientierten GUI-Rahmenwerk wie Qt braucht man das zwingend.

Das nächste sind gute Namen. Die sollte man sich vor objektorientierter Programmierung (OOP) bereits angewöhnt haben. `p`, `v`, `prop`, `vol`, `horizontalSlider`, `lcdNumber`, und erst recht durchnummerierte Varianten davon sind *keine guten Namen*. Namen sollen dem Leser vermitteln wofür der Wert in Kontext des Programms steht, und nicht zum rätselraten zwingen.

Warum hast Du `loadUiType()` anstelle von `loadUi()` verwendet? Das ist eher ungewöhnlich, vor allem weil Du in der `Main`-Klasse dann gar nichts implementierst.

Beim Verbinden der Signale mit den Slots hast Du die veraltete Variante verwendet statt die `connect()`-Methode auf den Signal-Attributen zu verwenden, was einfacher, weil kürzer, und sicherer ist, weil ein falsches Signal sofort beim Verbinden zu einer Fehlermeldung führt.

Warum einmal `valueChanged` und alle anderen Verbindungen mit `sliderMoved`?

Auf Modulebene sollten nur Definitionen von Konstanten, Funktionen, und Klassen stehen. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst und durch folgendes Idiom gestartet wird, damit man das Modul nicht nur direkt ausführen kann, sondern auch importieren kann ohne dass das Hauptprogramm gleich losläuft:

Code: Alles auswählen

if __name__ == '__main__':
    main()
Tom Brady
User
Beiträge: 9
Registriert: Freitag 4. Dezember 2015, 07:13

Hallo BlackJack,
vielen Dank für deine Antwort und für die wertvollen Tips (ist ernst gemeint).

Der Code ist eigentlich ein nur ein Ausschnitt aus einem längeren Code. Ich hatte nur aus das wesentliche rausgeschrieben, um auszuschließen, dass der Fehler außerhalb des Bereiches liegt. Dafür habe ich dann möglichst kurze Variablennamen vergeben um Zeit zu sparen.

Wenn ich "loadUiType()" statt "loadUi()" verwende, bekomme ich folgende Fehlermeldung:
'import sitecustomize' failed; use -v for traceback
QWidget: Must construct a QApplication before a QPaintDevice


Das mit "main" hab ich leider auch nicht verstanden. wenn ich "show" entferne, lautet der Fehler:
main()
TypeError: 'Main' object is not callable


"valueChanged" hatte ich mal probiert, nur um sicher zu sein, dass der Fehler nicht an einem falschen Signal liegt.

Also du meinst:

Code: Alles auswählen

main.horizontalSlider.valueChanged[int].connect(prop)
wäre besser als:

Code: Alles auswählen

main.connect(main.horizontalSlider, QtCore.SIGNAL('valueChanged(int)'), prop)
Nochmal Danke für deine Hilfe.
Grüße
BlackJack

@Tom Brady: Die Zeit die man einmal beim schreiben von schlechten Namen spart, muss man beim lesen dann jedes mal wieder investieren wenn ein Name deswegen unverständlich ist und man rätselt was das bedeutet. Zu generische Namen sind besonders nervig wenn man Fehler sucht weil es eben nicht offensichtlich ist wenn man statt eines `spam_3` ein `spam_2` hätte schreiben müssen, während ein falscher Name bei sinnvollen Bezeichnern deutlich einfacher zu finden ist.

Die Ausnahme bei `loadUi()` ist ja ziemlich eindeutig. Vorher muss halt ein `QApplication`-Exemplar existieren. Da das *die Anwendung* repräsentiert, ist das logischerweise das erste was man erstellt, bevor man irgendwelche Fenster erstellt.

`main()` heisst üblicherweise die Funktion in der das Hauptprogramm steht. Anstatt direkt auf Modulebene. Das Du Dein Fensterexemplar so genannt hast ist ein weiterer ungünstiger Name.
BlackJack

Hier mal ein Beispiel mit Trennung von Programmlogik und GUI, auch wenn die Logik ja noch eher bescheiden ist:

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


class SumLogic(object):

    def __init__(self, operand_a, operand_b):
        self.operand_a = operand_a
        self.operand_b = operand_b

    @property
    def sum(self):
        return self.operand_a + self.operand_b


class Window(object):

    def __init__(self, sum_logic):
        self.ui = loadUi('test.ui')
        self.sum_logic = sum_logic
        self.update_display()
        self.ui.operand_a_slider.valueChanged[int].connect(
            partial(self.on_operand_change, 'operand_a')
        )
        self.ui.operand_b_slider.valueChanged[int].connect(
            partial(self.on_operand_change, 'operand_b')
        )
        self.ui.show()

    def on_operand_change(self, operand_name, value):
        setattr(self.sum_logic, operand_name, value)
        self.update_display()

    def update_display(self):
        self.ui.operand_a_lcd.display(self.sum_logic.operand_a)
        self.ui.operand_b_lcd.display(self.sum_logic.operand_b)
        self.ui.sum_lcd.display(self.sum_logic.sum)


def main():
    application = QApplication(sys.argv)
    window = Window(SumLogic(0, 0))
    sys.exit(application.exec_())


if __name__ == '__main__':
    main()
Tom Brady
User
Beiträge: 9
Registriert: Freitag 4. Dezember 2015, 07:13

Oh, danke. jetzt hab ich endlich das Kapitel über Properties und Vererbung in dem Buch, was ich mir gekauft habe verstanden.
Damit kann ich was anfangen. Super.
Antworten