Welchen Sizer verwenden?

Plattformunabhängige GUIs mit wxWidgets.
Antworten
Benutzeravatar
C4S3
User
Beiträge: 292
Registriert: Donnerstag 21. September 2006, 10:07
Wohnort: Oberösterreich

Hallo und guten Morgen alle beisammen!

Gerade versuche ich, mit dem Rumspielen der diversen Widgets, die wxPython mir bietet, aufzuhören und das erste mehr oder weniger vollständige Programm zu schreiben, welches dann auch einen praktischen Nutzen erfüllen soll.
Da ich es leid bin, meine Arbeitsstunden immer in eine Excel-Liste einzutragen, dachte ich mir, dass dies doch eine nette Aufgabe wäre.

So, nun zum Layout!
Ich hätte meinen Frame (also das Hauptfenster) gerne in 3 Teile unterteilt. Das soll also ähnlich aussehen, wie in den meisten Mailprogrammen (e.g. Thunderbird): Links von oben bis unten ein Bereich, der entweder eine TreeCtrl oder so beinhaltet (darin sollen die Monate gelistet sein). Dann im rechten Bereich oben die Möglichkeit, Details zu einem Eintrag anzulegen, ein zu sehen, editieren, löschen. Und darunter eine Übersicht der Einträge / Monat.

(Misslungene Asci-Art:)

Code: Alles auswählen

+----+----------+
|    |          |
|    +----------|
|    |          |
|    |          |
+----+----------+
Mit welchem Sizer kann ich das eurer Meinung nach am besten lösen?

Danke schon mal für eure Anregungen.
Viele Grüße,
Gruß!
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

C4S3 hat geschrieben:So, nun zum Layout!
Hallo C4S3!

Na gut. Auf zum Layout. ;-)

Bild

Code ausgelagert: http://paste.pocoo.org/show/5668/

mfg
Gerold
:-)

PS: Vielleicht habe ich es mit den Panels übertrieben. Aber ich will sicher stellen, dass man mit Tab von einem Panel in das nächste springen kann und es macht auch die Erstellung etwas einfacher. Ansonsten müsste man den rechten Bereich mit den zwei untereinander liegenden Panels zuerst erstellen und dann in den Splitter legen, der dafür zuständig ist, den Bereich in zwei Spalten aufzuteilen. -- Alles hat seine Vor- und Nachteile...

EDIT: Code ausgelagert.
Zuletzt geändert von gerold am Dienstag 9. Oktober 2007, 10:06, insgesamt 6-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hi C4S3,

da ich mich zur Zeit auch mit Sizern befasse, kann ich mir nicht vorstellen, dass das was Du willst damit funktioniert.

Evtl. entspricht das dem Aufbau des wxPython Demo, ich würde mir dazu das Demo wxSplitterWindow ansehen.

In die drei Frames die Du dir so erstellst, kommt dann jeweils ein Panel, auf dem du deine Widgets mit Sizern positionierst.

Ich finde den GridBagSizer nicht schlecht, wenn du einen tabellarischen Aufbau hast. Ansonsten sind sicher die BoxSizer das Mittel der Wahl.

Gruß Christian

edit: zu Spät!
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Byte hat geschrieben:edit: zu Spät!
Hallo Christian!

Es ist niemals zu spät!

So sind es schon zwei gleiche Meinungen, die damit dem Fragenden mehr Sicherheit geben. Die Sicherheit, nicht nur die Meinung eines Einzelnen, der dir evt. nur etwas einreden will, angewiesen zu sein.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Byte
User
Beiträge: 63
Registriert: Dienstag 26. September 2006, 07:04

Hi Gerold,

bei mir ist es halt eine Vermutung, und Du kannst es halt. Ich hätte kein Beispiel zur Hand.

Gruß Christian :oops:
BlackJack

@gerold: Naja, man tauscht die Unsicherheit einer einzelnen Meinung gegen die Unsicherheit ob man es mit einer Verschwörung zu tun hat. ;-)
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

gerold hat geschrieben:Vielleicht habe ich es mit den Panels übertrieben.
Ja, ich habe übertrieben.

So funktioniert es auch -- nur viel einfacher: :oops:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import wx

wx.SetDefaultPyEncoding("iso-8859-15")


class MyFrame(wx.Frame):
    
    def __init__(
        self, parent = None, title = "Example", size = wx.Size(550, 420)
    ):
        wx.Frame.__init__(self, parent, -1, title, size = size)
        
        main_panel = wx.Panel(self)
        
        main_border = wx.BoxSizer(wx.VERTICAL)
        main_panel.SetSizer(main_border)
        
        vsplitter = wx.SplitterWindow(main_panel)
        main_border.Add(vsplitter, 1, wx.ALL | wx.EXPAND, 5)
        
        left_panel = wx.Panel(vsplitter)
        left_panel.SetBackgroundColour("green")
        hsplitter = wx.SplitterWindow(vsplitter)
        
        vsplitter.SplitVertically(left_panel, hsplitter)
        
        top_panel = wx.Panel(hsplitter)
        top_panel.SetBackgroundColour("blue")
        bottom_panel = wx.Panel(hsplitter)
        bottom_panel.SetBackgroundColour("yellow")
        
        hsplitter.SplitHorizontally(top_panel, bottom_panel)
        
        # Zum Testen der Tab-Taste
        txt1 = wx.TextCtrl(left_panel)
        txt2 = wx.TextCtrl(top_panel)
        txt3 = wx.TextCtrl(bottom_panel)


def main():
    app = wx.PySimpleApp()
    f = MyFrame()
    f.Center()
    f.Show()
    app.MainLoop()


if __name__ == "__main__":
    main()
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

BlackJack hat geschrieben:@gerold: Naja, man tauscht die Unsicherheit einer einzelnen Meinung gegen die Unsicherheit ob man es mit einer Verschwörung zu tun hat. ;-)
Hallo BlackJack!

Ich grüble jetzt schon mehrere Minuten... :mrgreen: Aber irgendwie fällt mir nichts ein, mit dem man dem entgegentreten könnte.

---

Ich bin Borg. Widerstand ist zwecklos.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
C4S3
User
Beiträge: 292
Registriert: Donnerstag 21. September 2006, 10:07
Wohnort: Oberösterreich

Vielen Dank für die Hilfe und Anregungen.
Da muss ich mich wohl jetzt durch kämpfen.
Mir kommt das alles sehr kompliziert vor. :oops:
Gruß!
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

C4S3 hat geschrieben:Mir kommt das alles sehr kompliziert vor. :oops:
Hallo C4S3!

Mit "wxPython in Action" wird es einfacher.

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
alan
User
Beiträge: 81
Registriert: Dienstag 10. April 2007, 11:30

Und generell kann ich sagen, dass man ziemlich schnell reinkommt. Einfach irgendeine Idee versuchen umzusetzen. Bei Problemen bekommt man hier super Hilfestellungen 8)
Benutzeravatar
C4S3
User
Beiträge: 292
Registriert: Donnerstag 21. September 2006, 10:07
Wohnort: Oberösterreich

Hallo nochmal!

Ich habe mir den obigen Code von gerold jetzt noch mal ganz genau angesehen und noch einige Fragen dazu. Nur um sicher zu gehen, dass ich es auch verstanden habe...
  • Also die Klasse instanziiert erst den Frame.
  • Darauf dann ein Panel (main_panel).
  • Das Panel bekommt einen vertikalen Box-Sizer (main_border) ...
  • ... und der Box-Sizer einen Splitter (vsplitter).
  • Dann wird ein weiteres Panel (left_panel) erzeugt und in den Splitter (vsplitter) gelegt.
  • Dann wird der erzeugt Splitter (vsplitter) nochmals durch einen Splitter (hsplitter) geteilt.
  • Dann werden 2 weitere Panels gemacht und durch den hsplitter separiert.
  • Und erst dann werden Widgets auf die einzelnen Panele gesetzt.
Puh, das ist ganz schön komplex. :?

Ist das immer notwendig? Ein Panel, darauf dann wieder Sachen zum Teilen, Vergrößern, .... und darin dann wieder Panels, auf denen dann Widgets platziert werden. Ich habe echt schon einen Knoten im Hirn.

Ich könnte doch aber theoretisch auch die paar Widgest die ich brauche "absolut" positionieren, oder? Da die Anwendung ausschließlich für mich ist, wäre ein R, ... ohnehin nicht gegeben.
Gruß!
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

C4S3 hat geschrieben:Ist das immer notwendig? Ein Panel, darauf dann wieder Sachen zum Teilen, Vergrößern, .... und darin dann wieder Panels, auf denen dann Widgets platziert werden. Ich habe echt schon einen Knoten im Hirn.
Deswegen gibt es in GTK+ das IMHO exzellente ``gtk.Table``, bei dem man so Dinge wunderbar definieren kann. So etwas würde wx sicher nicht schaden.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

Leonidas hat geschrieben:``gtk.Table``
Hallo Leonidas!

``gtk.Table`` -- das gibt es in wxPython auch.

wx.GridSizer --> Jede Zelle gleich groß. Die größte Zelle bestimmt die Größe aller Zellen.

wx.FlexGridSizer --> Die Zellen können sich in der Größe unterscheiden. Die Größe wird zeilenweise oder spaltenweise an die jeweils größte Zelle angepasst.

wx.GridBagSizer --> Wie wx.FlexGridSizer, mit dem Unterschied, dass Widgets mehrere Zellen einnehmen können.

lg
Gerold
:-)

PS: Ich glaube, ich werde mal eine kleine Anleitung schreiben.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

C4S3 hat geschrieben:Ist das immer notwendig? Ein Panel, darauf dann wieder Sachen zum Teilen, Vergrößern, .... und darin dann wieder Panels, auf denen dann Widgets platziert werden.
Hallo C4S3!

Ich muss mich bei dir entschuldigen. Du schriebst "...wie im Thunderbird". Das hat mich veranlasst, dir zu zeigen, wie man mit wx.SplitterWindow die Bereiche so erstellt, dass sich diese mit der Maus vergrößern und verkleinern lassen. Der gezeigte Aufwand ist nur dann nötig, wenn du das so mit den Splittern haben möchtest.

Wenn das nicht der Fall ist und du einfach nur ein dreigeteiltes Layout (ohne Splitter) haben möchtest, dann ist der Aufwand um einiges geringer (und überschaubarer).

mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

So geht's mit dem GridBagSizer (aber ich mag ihn nicht besonders):

Bild

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import wx

wx.SetDefaultPyEncoding("iso-8859-15")


class MyFrame(wx.Frame):
    
    def __init__(
        self, parent = None, title = "Example", size = wx.Size(550, 420)
    ):
        wx.Frame.__init__(self, parent, -1, title, size = size)
        
        panel = wx.Panel(self)
        
        vbox_main = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(vbox_main)
        
        # GridBagSizer erstellen und einstellen
        grid_sizer = wx.GridBagSizer(vgap = 5, hgap = 5)
        grid_sizer.AddGrowableCol(1) # zweite Spalte
        grid_sizer.AddGrowableRow(1) # zweite Zeile
        vbox_main.Add(grid_sizer, 1, wx.EXPAND | wx.ALL, 5)
        
        left_txt = wx.TextCtrl(panel, size = (100, -1), style = wx.TE_MULTILINE)
        grid_sizer.Add(left_txt, (0, 0), (2, 1), wx.EXPAND)
        
        top_txt = wx.TextCtrl(panel, size = (-1, 100), style = wx.TE_MULTILINE)
        grid_sizer.Add(top_txt, (0, 1), (1, 1), wx.EXPAND)
        
        bottom_txt = wx.TextCtrl(panel, style = wx.TE_MULTILINE)
        grid_sizer.Add(bottom_txt, (1, 1), (1, 1), wx.EXPAND)


def main():
    """Testing"""
    app = wx.PySimpleApp()
    f = MyFrame()
    f.Center()
    f.Show()
    app.MainLoop()


if __name__ == "__main__":
    main()
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

gerold hat geschrieben:So geht's mit dem GridBagSizer (aber ich mag ihn nicht besonders)
Und so funktioniert es, nur mit BoxSizer:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-15 -*-

import wx

wx.SetDefaultPyEncoding("iso-8859-15")


class MyFrame(wx.Frame):
    
    def __init__(
        self, parent = None, title = "Example", size = wx.Size(550, 420)
    ):
        wx.Frame.__init__(self, parent, -1, title, size = size)
        
        panel = wx.Panel(self)
        
        vbox_main = wx.BoxSizer(wx.VERTICAL)
        panel.SetSizer(vbox_main)
        
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        vbox_main.Add(hbox, 1, wx.EXPAND | wx.ALL, 3)
        
        left_txt = wx.TextCtrl(panel, size = (100, -1), style = wx.TE_MULTILINE)
        hbox.Add(left_txt, 0, wx.EXPAND | wx.ALL, 3)
        
        vbox = wx.BoxSizer(wx.VERTICAL)
        hbox.Add(vbox, 1, wx.EXPAND)
        
        top_txt = wx.TextCtrl(panel, size = (-1, 100), style = wx.TE_MULTILINE)
        vbox.Add(top_txt, 0, wx.EXPAND | wx.ALL, 3)
        
        bottom_txt = wx.TextCtrl(panel, style = wx.TE_MULTILINE)
        vbox.Add(bottom_txt, 1, wx.EXPAND | wx.ALL, 3)


def main():
    """Testing"""
    app = wx.PySimpleApp()
    f = MyFrame()
    f.Center()
    f.Show()
    app.MainLoop()


if __name__ == "__main__":
    main()
mfg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
C4S3
User
Beiträge: 292
Registriert: Donnerstag 21. September 2006, 10:07
Wohnort: Oberösterreich

Danke lieber Gerold!
Das sieht für meinen Wissensstand schon verträglicher aus. ;)

Aber irgendwie kommen doch mit jeder Antwort wieder neue Fragen. :(

Zum letzten Code:
Also: ein Panel und ne Vbox. Darin dann ne HBox mit wieder einer Vbox drin?

Und was mich an der Sache am meisten verwirrt und mir gleichzeitig auch vor Augen führt, dass ich das Konzept nicht verstanden habe:

Code: Alles auswählen

top_txt = wx.TextCtrl(panel, size = (-1, 100), style = wx.TE_MULTILINE)
vbox.Add(top_txt, 0, wx.EXPAND | wx.ALL, 3)
Ein Textcontrol, das als Parent das Panel hat und in der nächsten Zeile wird aber genau diese Objekt an die Vbox übergeben. Das verstehe icht nicht. Wie hängen dies zusammen? Sorgt die Box nicht dafür, dass das Panel vergrößert/verkleinert wird und mit ihm auch sein Inhalt?

Wo ist da mein Denkfehler? Ich begreife es (im Moment) einfach noch nicht. Und selbst wxP in Action, wxPython in one Page und die wxDemo helfen mir da irgendwie nicht weiter. Irgendwas lässt micht nicht dahinter kommen. *gleich rasend werd*

Danke für eure Mühen und Geduld.
Gruß!
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

C4S3 hat geschrieben:Ein Textcontrol, das als Parent das Panel hat und in der nächsten Zeile wird aber genau diese Objekt an die Vbox übergeben. Das verstehe icht nicht. Wie hängen dies zusammen? Sorgt die Box nicht dafür, dass das Panel vergrößert/verkleinert wird und mit ihm auch sein Inhalt?
Hallo C4S3!

Also, die Sache ist eigentlich ganz einfach. :twisted:

Ein Widget muss auf einem Container liegen. Frames, Dialogs, Panels und noch so ein paar Objekte sind solche Container.

Sizer sind keine Container. Sizer sind unsichtbare "Helfer", die sich **nur** darum kümmern, dass die Widgets auf dem Container korrekt angeordnet werden.

Man kann einem Container einen Sizer zuweisen. Dieser Sizer ist dann nur für die Anordnung der Widgets auf diesem Container zuständig.

Code: Alles auswählen

panel = wx.Panel(parent = self)
vbox = wx.BoxSizer(wx.VERTICAL)
panel.SetSizer(vbox)
Wenn ich jetzt ein neues Widget erstelle, dann lege ich es schon beim Erstellen auf einen Container.

Code: Alles auswählen

txt = wx.TextCtrl(parent = panel)
Damit liegt das Widget schon auf dem Container, aber es ist noch nicht korrekt angeordnet. Dafür binde ich das neue Widget zusätzlich an einen Sizer.

Jetzt könntest du fragen, warum macht das wxPython nicht automatisch? Es wurde dem Container ja schon ein Sizer zugeordnet. -- Die Antwort ist: Man kann an so einen unsichtbaren Sizer, nicht nur Widgets, sondern auch Sizer zuordnen. Dadurch, dass an einen Sizer auch noch andere Sizer gebunden werden können, kann man die vielfältigsten Layouts generieren. Aber wxPython kann nicht automatisch wissen, welcher Sizer jetzt für das neue, soeben in den Container gelegte, Widget zuständig ist. Deshalb machen wir das selbst. Wir binden das neue Widget selbst an einen Sizer und geben dabei auch noch an, wie und wo und mit welchem Abstand usw. das neue Widget vom Sizer angeordnet werden soll.

Code: Alles auswählen

vbox.Add(txt, proportion = 0, flag = wx.EXPAND | wx.ALL, border = 10)
Damit wird jetzt das neue TextCtrl, an den Sizer ``vbox`` gebunden. ``proportion`` gibt an, wie viel Teile des Gesamtplatzes von diesem Widget ausgefüllt werden soll. Bei einem vertikalen BoxSizer ist damit der Platz nach unten gemeint. Eine 0 gibt an, dass das Widget nur so viel Platz bekommt, wie viel es gerade mal benötigt.
Zahlen > 0 geben die Teile an. Gibt es im gesamten Sizer nur ein Widget und ist die Proportion dieses Widgets 1, dann wird es die gesamte Größe des Sizers ausfüllen.
Kommt noch ein zweites Widget dazu und ist dessen Proportion 2, dann wird das erste Widget ein Drittel und das zweite Widget zwei Drittel des Platzes von oben nach unten ausfüllen.

Mit dem Flag wx.EXPAND gibt man an, dass das Widget den gesamten Bereich innerhalb des Sizers, von links nach rechts ausfüllen soll. Bei einer vertikalen Box ist die Proportion immer auf den vertikalen Bereich bezogen. wx.EXPAND bezieht sich damit bei einer vertikalen Box auf den horizontalen Bereich.

Bei einer horizontalen Box ist die Proportion immer auf den horizontalen Bereich innerhalb dieses Sizers bezogen. wx.EXPAND bezieht sich damit bei einer horizontalen Box auf den vertikalen Bereich.

Aber ich glaube, in wxPython in Action wird das viel schöner erklärt.

EDIT:

Nachzulesen in "wxPython in Action" auf den Seiten 323 bis 355.

mfg
Gerold
:-)
Zuletzt geändert von gerold am Donnerstag 11. Oktober 2007, 08:28, insgesamt 1-mal geändert.
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
Benutzeravatar
C4S3
User
Beiträge: 292
Registriert: Donnerstag 21. September 2006, 10:07
Wohnort: Oberösterreich

gerold hat geschrieben:Aber ich glaube, in wxPython in Action wird das viel schöner erklärt.
Nein, wird es IMHO nicht.

Danke für die Erklärung. Das hilft jetzt echt enorm! *verbeug*
Gruß!
Antworten