PyQt4 - zu öffnendes Widget schließt sofort wieder

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
hirnwunde
User
Beiträge: 15
Registriert: Mittwoch 3. September 2014, 09:41

Hallo Leute,

ich "spiele" nun seit einigen Tagen mit Python und versuche mich gerade an Qt.
Nach meinen ersten Gehversuchen mit Buttons, Slots und Signalen in einem Fenster versuche
ich nun mehrere Fenster darzustellen.

Ziel soll es sein, dass ich mittels Button ein weiteres Fenster öffnet, welches sich (wieder durch
einen Button) selber schließt.

Ich habe im Qt-Designer also ein MainWindow und ein Widget erstellt, diese mit pyuic4 in
Python-Code gewandelt und sie in mein main.py-Script importiert.

Das zweite Fenster öffnet sich auch brav.
Nur schließt es sich auch gleich wieder, nachdem es kurz aufploppte.

Ich nutze Python 2.7.8 auf win32 und PyQt 4.11.1 in Verbindung mit eclipse & PyDev.

Die Scripte sind:

main.py
wdg_settings.py
hwCNCPythonEdition.py

Wenn es euch lieber ist, dass ich den Code in dem Thread selbst poste, werde ich dies machen.
Dachte aber, das macht den Beitrag nur unnötig lang.

Danke schonmal im Voraus.
BlackJack

@hirnwunde: Das sieht alles ein wenig durcheinander aus und als wenn unabhängig von der GUI die objektorientierte Programmierung schon nicht richtig verstanden wurde. So etwas wie folgendes ist einfach nur WTF!?:

Code: Alles auswählen

    def settingsWin(self):
        #print("Blubb")
        SettingsWidget.ShowWidget(SettingsWidget())
Du rufst auf der *Klasse* `SettingsWidget` die ungebundende `ShowWidget()`-Methode mit einem dafür erstellten Exemplar von `SettingsWidget` auf. Das in seiner `__init__()` selber `show()` aufruft, was dann die `ShowWidget()`-Methode noch mal macht, aber das Widget-Objekt wird nirgends ”gespeichert” sondern nur für diesen Aufruf erzeugt und es verschwindet danach wieder ins Nirwana.
hirnwunde
User
Beiträge: 15
Registriert: Mittwoch 3. September 2014, 09:41

Nachdem ich hier und auf SO noch weitere Beiträge laß, muss ich Dir wohl voll und ganz recht geben.

Ich habe zu wenig von OOP verstanden!

Das 'show()' in der __init__ blieb erhalten, als ich die Klasse schrieb.
Das sollte da eigentlich nicht stehen, habe ich uebersehen.
Mir is bewusst, dass der doppelte Aufruf (einmal in der Initialisierung und
spaeter nochmal in ShowWidget()) geistiger Durchfall meinerseits ist.

Warum das hier?

Code: Alles auswählen

SettingsWidget.ShowWidget(SettingsWidget())
Weil der Interpreter mir die Meldung

Code: Alles auswählen

TypeError: unbound method ShowWidget() must be called with SettingsWidget instance as first argument (got nothing instead)
gab.

Aus meiner Unkenntnis heraus habe ich also die Instanz SettingWidget() mitgegeben ...

Ich muss dann wohl "nochmal auf die Schulbank" zurueck, Qt erstmal
zur Seite legen und mich intensiv mit OOP beschaeftigen.

Entschuldigt die Störung! ;-)
Benutzeravatar
Madmartigan
User
Beiträge: 200
Registriert: Donnerstag 18. Juli 2013, 07:59
Wohnort: Berlin

Da gibt es nichts zu entschuldigen, du störst doch niemanden. :-)

Die Fehlermeldung meint, dass du die Methode nicht als statische Methode aufrufen kannst. In dem Fall wäre die Instanz also nicht als Parameter zu übergeben, sondern muss die aufrufende Instanz selbst sein.

Ergo statt:

Code: Alles auswählen

SettingsWidget.ShowWidget()
wäre folgendes valide:

Code: Alles auswählen

SettingsWidget().ShowWidget()
oder

Code: Alles auswählen

mySettingsWidget = SettingsWidget()
mySettingsWidget.ShowWidget()
Aber, wie du selbst bemerkt hast, für GUI Entwicklung muss man sattelfest in OOP sein. Verständnis für Parent-Child-Beziehungen sind hier elementar.
Bleib dran!
hirnwunde
User
Beiträge: 15
Registriert: Mittwoch 3. September 2014, 09:41

Danke für die Aufklärung. (Klammerfehler)

Das Prinzip der OOP habe ich schon vor einigen Jahren kennengelernt.
Allerdings habe ich, bis ich vor 4 Jahren komplett auf VB.Net schwang, immer prozedural programmiert.
Aber selbst in VB.Net muss man sich fast garnicht mit OOP beschäftigen.

Da ich in meiner jetzigen Firma aber nichts bzw. nur sehr eingeschränkt mit Perl, bash oder PHP
programmieren kann (90% der Rechner laufen hier auf Windows, 8% auf MacOS, und meine 2%
teilen sich Linux und BSD) habe ich angefangen, mich mit Visual Studio anzufreunden.

Die GUI-Programmierung selbst in den Express-Versionen sind, sagen wir mal, sehr Benutzerfreundlich.
Was am Ende an konsistenten Code dabei herauskommt, kann ich als Hobby-Programmierer nicht bewerten.

Um die Jahrtausendwende hatte ich mich mit GTK befasst.
Nur kurz.
Das war mir damals viel zu hoch. OOP war da für mich ein Buch mit sieben Siegeln.

Dann wurde ich mit Excel und VBA immer mehr in die OOP-Ecke "gedrängt".
Eigene Klassen zu schreiben war da aber noch nicht drin.

Lange Rede, kurzer Sinn:

Python ist für mich der Weg, mit einem Skript MacOS, Windows und Unices abzudecken.
Das ich deswegen nun OOP verinnerlichen muss, wurde mir erst vor kurzem bewusst.

Aber ich bin guter Dinge!
Vor allem der freundliche Umgang hier gefällt mir. Ich habe zwar nur sehr wenige Beiträge aus
diesem Forum gelesen, aber ich denke, der Grundton ist hier um längen angenehmer als bspw. auf mikrocontroller.net

Happy hacking!
BlackJack

@hirnwunde: Aus den Designer-Dateien würde ich übrigens keinen Quelltext generieren. Mit dem `PyQt4.uic`-Modul kann man die ``*.ui``-Dateien zur Laufzeit laden und in Widgets umsetzen lassen. Damit spart man sich den Zwischenschritt aus den ``*.ui``-Dateien immer erst ``*.py``-Dateien machen zu müssen.

Bei dem GUI-Entwurf solltest Du ausserdem aufhören die Elemente an absoluten Positionen zu platzieren und Layouts verwenden. Die beiden Widgets sehen bei mir zum Beispiel nicht ”perfekt” aus. Abgeschnittene Texte und teilweise leere Fensterflächen wo wahrscheinlich keine sein sollten.
hirnwunde
User
Beiträge: 15
Registriert: Mittwoch 3. September 2014, 09:41

Bei meinen gestriegen Nachforschungen bzg. dem fehlerhaften, weil nicht
verstandenen, Code habe ich das mit dem zur Laufzeit zu ladenen .ui-Dateien
auch schon gesehen.
Danke für den Hinweis!

Das mit der absoluten Positionierung ist für mich bisher der einzig bekannte Weg,
verschieden grosse Elemente neben- bzw. untereinander zu platzieren, die die Rahmen
der einzelnen Boxen verlassen, ohne das das kleinere Element dem Größtem in seiner
Ausdehnung angepasst wird.

Das Form-Layout kommt dem schon ganz nah, aber eben auch nicht soo präzise wie
die absolute Positionierung.

Beispiel:

Code: Alles auswählen

+---+------------------------------------------------------------------------------------------+---+
|   | Hauptfenster                                          _                                  | X |
+---+--------------------------------------------------------------------+-----------------------+-+
|                                                                        +-----------------------+ |
| +----------------+                                                     |                       | |
| |     Button1    |          +---------+---+                            |  Textfield3           | |
| +----------------+          |DropDown | V |                            |                       | |
| +----------------+          +---------+---+                            |                       | |
| |     Button2    |                                                     |                       | |
| +----------------+                                                     |                       | |
|                                                                        |                       | |
| +-------------------------------+    +------------------------------+  |                       | |
| |                               |    |                              |  |                       | |
| |  Textfield1                   |    | Textfield2                   |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| |                               |    |                              |  |                       | |
| +------------+-----+------------+    +----------+-------------------+  +-----------------+-+---+ |
| +------------+     +------------+    +----------+                      |-----------------| +---+ |
| | Button3    |     | Button4    |    | Button5  |                      +-----------------+ | B6| |
| +------------+     +------------+    +----------+                                          +---+ |
+-+------------+-----+------------+----+----------+------------------------------------------+---+-+
Wenn ich das jetzt in einem horizontal-vertikal-Mix positionieren möchte,
wird Button1 und Button2 auf die Größe von Textfield1 verbreitert.
DropDown ist nicht an dieser Position platzierbar, da es sowohl die horizontale als
auch die vertikale Box überschneidet.

In einem Form-Layout würde in diesem Beispiel nur DropDown nicht dort zu
positionieren sein, da es die Formbox der linken Form schneidet.

Im Gridlayout sieht es nicht besser aus. Auch hier bin ich durch die Grenzen
der einzelnen Boxen beschränkt.
Bild

Das dies zu Problemen mit der Darstellung auf unterschiedlichen Systemen kommt,
ist mir bewusst. Aber ich habe mir da noch keine genaueren Gedanken drüber gemacht.
Meine ersten, nicht tiefergehenden, Überlegungen waren, einen Font zu wählen,
welcher auf allen Systemen verfügbar und ansatzweise gleich dargestellt wird.

Aber ... wie wir ja schon festgestellt haben, habe ich erst einmal andere Hausaufgaben
zu erfüllen.

Bisher bin ich nach dran, mir mein Programm erstmal ohne GUI zu basteln und zu gucken,
das die Funktionen so funktionieren, wie sie funktionieren sollen.

Alles was GUI betrifft wird sich wohl noch um ein bis zwei Wochen verschieben.

Ich bin halt das Visual Studio-Programmieren gewohnt.
Da bastel ich mir erst das GUI und weise dann den Elementen
die Logik zu.
Sicher war/ist das auch im Visual Studio der falsche Weg.
Das hatte bei mir mit meinem Popel-Projekten aber immer gut funktioniert. ;-)
BlackJack

@hirnwunde: Ich weiss nicht ob ich Dein Layoutproblem verstanden habe. Kann es sein dass Du versuchst den gesamten Fensterinhalt mit *einem* Layout zu gestalten? Man kann ja an den einzelnen Stellen, zum Beispiel in einer ”Zelle” von einem Box- oder Gridlayout ein `QWidget` platzieren und darin ein weiteres/anderes Layout benutzen. Ansonsten muss man halt machen was die Layouts an Möglichkeiten hergeben, denn ansonsten hat man halt keine Möglichkeit eine GUI so zu gestalten das die überall vernünftig benutzbar ist.

Das mit dem Zeichensatz aussuchen geht nicht weil die Zeichengrösse ja in der Regel vom Benutzer vorgegeben wird und auch werden sollte, denn der muss sich das ja letztendlich so einstellen, das er das auf seiner Displaygrösse/Auflösung *lesen* kann. Die Schriftgrösse wird auch in physikalischen Grössen vorgegeben, während die absolute Platzierung in Pixeln passiert.
hirnwunde
User
Beiträge: 15
Registriert: Mittwoch 3. September 2014, 09:41

Hallo BlackJack.

Erstmal danke, das Du dir so viel Zeit nimmst!
Und entschuldige die spaete Antwort.
Dummerweise hat sich mein Sohn heut im Hort verletzt und er musste operiert werden.
Das hat unseren gewohnten Tagesablauf etwas ueber den haufen geworfen und ich finde
jetzt erst etwas Zeit, mich wieder mit Python zu beschaeftigen.

Aber wie ich anfangs schon erwaehnte, werde ich mich erstmal auf das verstehen
von OOP in Python und dem Aufbau der Lokig meines Programmes widmen.

Ich werde sicherlich spaeter nochmal auf Deine Hilfe angewiesen sein bzw.
deinen Anmerkungen und/oder Erlaeuterungen ein offenes Ohr schenken.

Wenn ich sehe, was Du so an Sprachen drauf hast (habe deinen ASM-Code auf der
Brotbuechse gesehen, der mit C und Python auf dem RasPi "konkuriert". Hut ab!)
wirst du sicher auch etwas VB drauf haben ;)
Denn mein jetziges Programm ist in VB.Net geschrieben und steuert meinen CNC-Plotter.
Dies moechte ich nun in Python nachbauen :)

Zu finden ist dies auf Github
(wenn Du ein Kompilat haben willst, gib bescheid)

Ich glaube, ich muss mich einfach von genau diesem layout verabschieden und ein
etwas einfacher zu erstellendes/verwaltendes entscheiden.

Aber ... erstmal habe ich andere Baustellen.
Sobald ich diese geloest habe, kuemmere ich mich wieder um die GUI.

Happy hacking!
BlackJack

@hirnwunde: Gute Besserung für den Nachwuchs.

Ich habe auf Basis von dem was Dein Beispiel aus dem ersten Beitrag anzeigt eine UI-Datei mit Layouts erstellt die etwas ähnliches anzeigt: http://www.python-forum.de/pastebin.php?mode=view&s=402

VB habe ich auch mal verwendet. War meine erste Sprache nach dem Wechsel von DOS auf Windows, also schon ziemlich lange her. :-)
hirnwunde
User
Beiträge: 15
Registriert: Mittwoch 3. September 2014, 09:41

Danke ... der geht schon wieder in die Schule ...war "nur" bis Sonntag im KKH.

Danke fuer das Layout.
Aber wie Du ja weisst, hapert es eher an anderen Stellen als an der Erstellung des UI ;) Aber das geht ja hier nicht verloren und ich werde sicher spaeter darauf zurueckgreifen.

Bis dahin sehen wir uns erstmal weiter in der anderen Forum-Abteilung ;)
Antworten