Zu kleines Notebook (--Nachtrag--)

Plattformunabhängige GUIs mit wxWidgets.
Antworten
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Da TkInter nicht genügend Funktionsumfang bietet möchte ich jetzt auf wxPython umsteigen. In einem ersten kleinen Programm tauchen aber bereits Probleme auf, die ich nicht zuletzt durch die schlechte Dokumentation nicht allein lösen kann.
Als erstes mein etwas gekürztes Programm:

Code: Alles auswählen

#!/usr/local/bin/python
# -*- coding: cp1252 -*-
# File: MedForm.py

import wx


class my_notebook(wx.Notebook):
    def __init__(self, parent):
        wx.Notebook.__init__(self, parent, -1)

        panel = wx.Panel(self, -1)
        sizer = wx.BoxSizer(wx.VERTICAL)

        box = wx.BoxSizer(wx.HORIZONTAL)
        label = wx.StaticText(panel, -1, 'Text')
        box.Add(label, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.hba1c = wx.TextCtrl(panel, -1, '', size=(80, -1))
        self.hba1c.SetFocus()
        box.Add(self.hba1c, 1, wx.ALIGN_CENTRE|wx.ALL, 5)
        sizer.Add(box, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

        self.mbz = wx.StaticText(panel, -1, 'Text')
        sizer.Add(self.mbz, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 10)

        line = wx.StaticLine(panel, -1, size=(20, -1), style=wx.LI_HORIZONTAL)
        sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

        btn = wx.Button(panel, -1, 'Text')
        btn.SetDefault()
        self.Bind(wx.EVT_BUTTON, self.on_mbz_click, btn)
        sizer.Add(btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5)

        sizer.Fit(panel)
        panel.SetSizer(sizer)

        self.AddPage(panel, 'Text')

#------------------------------------------------------------------------------

        panel = wx.Panel(self, -1)
        sizer = wx.BoxSizer(wx.VERTICAL)

        grid = wx.FlexGridSizer(3, 2)
        label = wx.StaticText(panel, -1, 'Text')
        grid.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        self.alter = wx.TextCtrl(panel, -1, '', size=(80, -1))
        grid.Add(self.alter, 0, wx.ALIGN_CENTRE|wx.ALL, 5)

        label = wx.StaticText(panel, -1, 'Text')
        grid.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        self.gewicht = wx.TextCtrl(panel, -1, '', size=(80, -1))
        grid.Add(self.gewicht, 0, wx.ALIGN_CENTRE|wx.ALL, 5)

        label = wx.StaticText(panel, -1, 'Text')
        grid.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 5)
        self.krea = wx.TextCtrl(panel, -1, '', size=(80, -1))
        grid.Add(self.krea, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        sizer.Add(grid, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

        box_title = wx.StaticBox(panel, -1, 'Text')
        stat_box = wx.StaticBoxSizer(box_title, wx.HORIZONTAL)
        self.mann = wx.RadioButton(panel, -1, 'Text', style = wx.RB_GROUP)
        stat_box.Add(self.mann, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.Bind(wx.EVT_RADIOBUTTON, self.on_select, self.mann)
        self.mann.SetValue(1)
        self.geschlecht = 1
        self.frau = wx.RadioButton(panel, -1, 'Text')
        stat_box.Add(self.frau, 0, wx.ALIGN_CENTRE|wx.ALL, 5)
        self.Bind(wx.EVT_RADIOBUTTON, self.on_select, self.frau)
        self.frau.SetValue(0)
        sizer.Add(stat_box, 0, wx.ALIGN_CENTRE|wx.ALL, 5 )

        self.gfr = wx.StaticText(panel, -1, 'Text')
        sizer.Add(self.gfr, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALL, 10)

        line = wx.StaticLine(panel, -1, size=(20, -1), style=wx.LI_HORIZONTAL)
        sizer.Add(line, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 5)

        btn = wx.Button(panel, -1, 'Text')
        btn.SetDefault()
        self.Bind(wx.EVT_BUTTON, self.on_gfr_click, btn)        
        sizer.Add(btn, 0, wx.ALIGN_CENTRE|wx.ALL, 5)

        sizer.Fit(panel)
        panel.SetSizer(sizer)

        self.AddPage(panel, 'Text')

    def on_mbz_click(self, event):
    	pass

    def on_select(self, event):
    	pass

    def on_gfr_click(self, event):
    	pass


class MyApp(wx.App):
    def OnInit(self):
        frame = wx.Frame(None, -1, 'Titel')
        nb = my_notebook(frame)
        self.SetTopWindow(frame)
        frame.Show(True)
        return True
        
app = MyApp()
app.MainLoop()
Das Notebook ist zu flach und unnötig breit. Ich kann die Größe aber auch nicht manuell mit size=(w, h) verändern. Was ist hier falsch?
Weiterhin möchte ich den Eingabecursor auf ein TextCtrl-Widget, z.B. self.hba1c setzen. SetFocus funktioniert aber nicht. Was muß ich anders machen?

Danke im voraus
HWK
Zuletzt geändert von HWK am Donnerstag 17. August 2006, 21:02, insgesamt 2-mal geändert.
Benutzeravatar
DatenMetzgerX
User
Beiträge: 398
Registriert: Freitag 28. April 2006, 06:28
Wohnort: Zürich Seebach (CH)

Das Notebook passt sich am Frame an ;) Setzt beim Frame eine kleinere Grösse und es geht

Code: Alles auswählen

class MyApp(wx.App):
    def OnInit(self):
        frame = wx.Frame(None, -1, 'Titel', size=(50,100))
        nb = my_notebook(frame)
        nb.hba1c.SetFocus()     #Focus erst später setzten, sonst wird er überschrieben
        self.SetTopWindow(frame)
        frame.Show(True)
        return True
Benutze noch ein wenig aussagekräftigere Namen. Ka welches Feld hba1c ist :s
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Vielen Dank für den Tip. Die Größe des Notebooks konnte ich jetzt nach meinen Wünschen anpassen. Das Setzen des Focus funktioniert aber noch nicht, wie ich mir das vorgestellt habe. Ich möchte beim Seitenwechsel im Notebook jeweils einem bestimmten TextCtrl den Focus übergeben. Auch ein Setzen des Focus im EVT_NOTEBOOK_PAGE_CHANGED funktioniert nicht. Hat jemand eine Idee?
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Beim Wechseln der Notebook-Seite erhält immer das Notebook selbst den Focus. Ich binde deshalb an den EVT_SET_FOCUS des Notebooks eine Routine, die den Focus auf mein je nach der gewählten Seite gewünschtes TextCtrl setzt. Also:

Code: Alles auswählen

class my_notebook(wx.Notebook):
    def __init__(self, parent):
.
.
.
        self.Bind(wx.EVT_SET_FOCUS, self.on_focus_set)
.
.
.
    def on_focus_set(self, event):
        if self.GetSelection() == 0:
            self.alter.SetFocus()
        else:
            self.hba1c.SetFocus()
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Meine letzte Lösung funktioniert leider nur bei lediglich 2 Seiten und nur, wenn die schon gewählte Seite nicht erneut ausgewählt wird.
Da unter Windows GetSelection denselben Wert wie GetOldSelection liefert, hatte ich einfach den Test in on_focus_set vertauscht:
self.alter liegt ja auf Seite 1 und nicht auf Seite 0.
Bei mehr als 2 Seiten weiß man aber nicht, mit welcher Seite man tauschen soll. Ich habe deshalb jetzt die Bestimmung der neu gewählten Seite durch Abfangen des Linksclicks im Notebook und Bestimmung der Seite aus der Mausposition mittels HitTest() durchgeführt, also:

Code: Alles auswählen

class my_notebook(wx.Notebook):
    def __init__(self, parent):
.
.
.
        self.Bind(wx.EVT_SET_FOCUS, self.on_focus_set)
        self.Bind(wx.EVT_LEFT_DOWN, self.on_left_down)
.
.
.
    def on_focus_set(self, event):
        (self.hba1c, self.alter)[self.index].SetFocus()

    def on_left_down(self, event):
        self.index = self.HitTest(wx.Point(event.m_x, event.m_y))[0]
        event.Skip()
Das funktioniert jetzt auch bei beliebig vielen Seiten. Auch das Anwählen einer bereits ausgewählten Seite stört nicht mehr.
Benutzeravatar
HWK
User
Beiträge: 1295
Registriert: Mittwoch 7. Juni 2006, 20:44

Nachtrag:
Ich habe neue Seiten in das Notebook eingefügt. Dadurch mußte die Fenstergröße angepaßt werden. Das ist auf Dauer natürlich nervig. Ich habe deshalb eine neue Lösung gesucht und gefunden. Die Größe des Frames wird erst nach Erstellen des Notebooks mit SetClientSize festgelegt. Dazu werden die größte Breite und Höhe der panels der einzelnen Notebook-Seiten verwendet. Leiter werden bei der Größe der Panels nicht die Notebook-Reiter berücksichtigt. Ich habe dafür einfach 2 Zeilenhöhen addiert. Gibt es eine Möglichkeit, die Größe einer kompletten Notebook-Seite einschließlich Reiter zu bestimmen?
Damit das Notebook lesbar bleibt, habe ich die minimale Größe gleich der aktuell berechneten gesetzt:

Code: Alles auswählen

        
        parent.SetClientSize((self.width, self.height +
                              2 * self.GetTextExtent(' ')[1]))
        # Zwei Zeilen größer wegen Notebook-Reitern
        # self.width und self.height entsprechen der max. Breite bzw. Höhe
        # der panels im Notebook
        parent.SetMinSize(parent.GetSize())
Antworten