Problem mit Sizern, Show() und Layout()

Plattformunabhängige GUIs mit wxWidgets.
Antworten
danx4
User
Beiträge: 2
Registriert: Dienstag 4. Januar 2011, 17:40

Hallo zusammen,

ich habe jetzt echt einiges ausprobiert, aber langsam fallen mir die Haare aus deswegen...!

Folgendes Problem: Ich habe eine geschachtelte Sizer-Struktur (Main-BoxSizer mit mehreren Sub-BoxSizern) auf meinem Panel und versuche einen der Sub-Sizer auszublenden. Dies funktioniert jedoch nicht wie gewünscht. Um das Problem zu veranschaulichen, habe ich mal ein ausführbares Beispiel erstellt.

Zur Erläuterung: Das gewünschte Verhalten kann durch das aufeinanderfolgende Drücken der Buttons "Show", "Count" und "Hide" erreicht werden. In diesem Fall werden zunächst zwei Statusleisten eingeblendet, danach zählen sie hoch und abschließend werden sie wieder ausgeblendet. Das gleiche Verhalten sollte sich nun ebenfalls beim Drücken des Buttons "Start" einstellen, jedoch tut es das bei mir nicht. Die beiden Statusleisten erscheinen hier zwar und werden auch korrekt befüllt, jedoch ist der Boxsizer nicht richtig sichtbar und auch die statischen Textfelder werden nicht richtig angezeigt.

Ach ja:
Python: 2.6.4
wxPython: 2.8.10.1

Code: Alles auswählen

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

import wx
import time

# **********************************************
# *** Constants
# **********************************************
GAUGE_RANGE = 10                                                            


# **********************************************
# *** Classes
# **********************************************
class ExpApp(wx.App):
    def __init__(self, redirect=False, filename=None):
        wx.App.__init__(self, redirect, filename)       
        self.Frame = ExpFrame(parent=None, id=wx.ID_ANY)
        self.Frame.Show(True)
        self.SetTopWindow(self.Frame)
        
class ExpFrame(wx.Frame):
    def __init__(self, parent=None, id=wx.ID_ANY, title='', pos=wx.DefaultPosition, size=wx.DefaultSize):
        wx.Frame.__init__(self, parent, id, title, pos, size)
        self.Panel = ExpPanel(parent=self, id=wx.ID_ANY)
 
class ExpPanel(wx.Panel):
    def __init__(self, parent=None, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize):
        wx.Panel.__init__(self, parent, id, pos, size, style=wx.NO_BORDER)
        self.parent = parent

        ### Controls for list 
        self.listCtrl      = wx.ListCtrl(parent=self, id=wx.ID_ANY, style=wx.LC_REPORT, size=(310,-1))
        statBoxList        = wx.StaticBox(parent=self, id=wx.ID_ANY, label='List:')
        boxSizerList       = wx.StaticBoxSizer(statBoxList, wx.VERTICAL)
        boxSizerList.Add(self.listCtrl,       1, wx.CENTER|wx.EXPAND)

        ### Controls for gauge 1
        self.statTextGauge1 = wx.StaticText(parent=self, id=wx.ID_ANY, label='Progress 1:', size=(100,-1))        
        self.gaugeProgress1 = wx.Gauge(parent=self, id=wx.ID_ANY, range=GAUGE_RANGE, size=(250, 20))
        boxSizerGauge1      = wx.BoxSizer(wx.HORIZONTAL)
        boxSizerGauge1.Add(self.statTextGauge1, 0, wx.CENTER)
        boxSizerGauge1.Add(self.gaugeProgress1, 1, wx.CENTER)
        ### Controls for gauge 2
        self.statTextGauge2 = wx.StaticText(parent=self, id=wx.ID_ANY, label='Progress 2:', size=(100,-1))        
        self.gaugeProgress2 = wx.Gauge(parent=self, id=wx.ID_ANY, range=GAUGE_RANGE, size=(250, 20))
        boxSizerGauge2      = wx.BoxSizer(wx.HORIZONTAL)
        boxSizerGauge2.Add(self.statTextGauge2, 0, wx.CENTER)
        boxSizerGauge2.Add(self.gaugeProgress2, 1, wx.CENTER)
        ### Box sizer for gauges
        statBoxProgress     = wx.StaticBox(parent=self, id=wx.ID_ANY, label='Progress:')
        boxSizerProgress    = wx.StaticBoxSizer(statBoxProgress, wx.VERTICAL)
        boxSizerProgress.Add(boxSizerGauge1,    1, wx.CENTER|wx.EXPAND|wx.BOTTOM, 4)
        boxSizerProgress.Add(boxSizerGauge2,    1, wx.CENTER|wx.EXPAND|wx.BOTTOM, 4)
        
        ### Controls for logger
        self.textCtrlLog    = wx.TextCtrl(parent=self, id=wx.ID_ANY, value='' )
        statBoxLogger       = wx.StaticBox(parent=self, id=wx.ID_ANY, label='Log:')
        boxSizerLogger      = wx.StaticBoxSizer(statBoxLogger, wx.VERTICAL)
        boxSizerLogger.Add(self.textCtrlLog,    1, wx.CENTER|wx.EXPAND|wx.ALL, 5)
        
        ### Controls for buttons
        self.buttonShow     = wx.Button(parent=self, id=wx.ID_ANY, label='Show')
        self.buttonCount    = wx.Button(parent=self, id=wx.ID_ANY, label='Count')
        self.buttonHide     = wx.Button(parent=self, id=wx.ID_ANY, label='Hide')
        self.buttonStart    = wx.Button(parent=self, id=wx.ID_ANY, label='Start')
        self.buttonShow.Bind(wx.EVT_BUTTON, self.EvtButtonShow)
        self.buttonCount.Bind(wx.EVT_BUTTON, self.EvtButtonCount)
        self.buttonHide.Bind(wx.EVT_BUTTON, self.EvtButtonHide)
        self.buttonStart.Bind(wx.EVT_BUTTON, self.EvtButtonStart)
        boxSizerButtons     = wx.BoxSizer(wx.HORIZONTAL)
        boxSizerButtons.Add(self.buttonShow,    0, wx.CENTER)
        boxSizerButtons.AddSpacer( (5,0) )        
        boxSizerButtons.Add(self.buttonCount,    0, wx.CENTER)        
        boxSizerButtons.AddSpacer( (5,0) )
        boxSizerButtons.Add(self.buttonHide, 0, wx.CENTER) 
        boxSizerButtons.AddSpacer( (5,0) )
        boxSizerButtons.Add(self.buttonStart, 0, wx.CENTER) 
        
        ### Main sizer        
        self.boxSizerMain = wx.BoxSizer(wx.VERTICAL)
        self.boxSizerMain.Add(boxSizerList,     1, wx.EXPAND|wx.ALL,   3)
        self.boxSizerMain.Add(boxSizerProgress, 0, wx.EXPAND|wx.ALL,   3)
        self.boxSizerMain.Add(boxSizerLogger,   1, wx.EXPAND|wx.ALL,   3)
        self.boxSizerMain.Add(boxSizerButtons,  0, wx.CENTER|wx.ALL,   3)
      
        ### Set the sizer
        self.SetSizer(self.boxSizerMain)
        ### Fit window to sizer
        self.boxSizerMain.Fit(self)
        
        ### Hide progress bar
        self.ShowProgressBar(False)
     
    ### Event functions
    def EvtButtonShow(self,evt):
        self.ShowProgressBar(True)
    def EvtButtonCount(self, evt):
        self.Count()
    def EvtButtonHide(self,evt):
        self.ShowProgressBar(False)
    def EvtButtonStart(self, evt):
        self.ShowProgressBar(True)
        self.Count()
        self.ShowProgressBar(False)
    
    ### Other functions
    def ShowProgressBar(self, inpFlag):
        self.gaugeProgress1.SetValue(0)
        self.gaugeProgress2.SetValue(0)
        self.boxSizerMain.GetChildren()[1].Show(inpFlag)
        self.boxSizerMain.RecalcSizes()
        self.boxSizerMain.Layout()
    def Count(self):
        for value in range(0,GAUGE_RANGE+1):
            self.gaugeProgress1.SetValue(value)
            time.sleep(0.1)
        for value in range(0,GAUGE_RANGE+1):
            self.gaugeProgress2.SetValue(value)  
            time.sleep(0.1)

            
# **********************************************
# *** Functions
# **********************************************
def StartApp():
    appObject = ExpApp()
    appObject.MainLoop()


# **********************************************
# *** Global entry point
# **********************************************
if (__name__ == '__main__'):
    StartApp()
Wäre super, wenn mir hier jemand erläutern könnte, was ich falsch mache. Vielen Dank schonmal!
ntrunk
User
Beiträge: 83
Registriert: Sonntag 7. September 2008, 23:09
Wohnort: Buchen (Odenwald)

danx4 hat geschrieben:Hallo zusammen,

ich habe jetzt echt einiges ausprobiert, aber langsam fallen mir die Haare aus deswegen...!
Das ist glücklicherweise kein Problem. Jeder Haarausfall hört irgendwann von selbst auf :wink:
danx4 hat geschrieben:[...]
Wäre super, wenn mir hier jemand erläutern könnte, was ich falsch mache. Vielen Dank schonmal!
Du gibst wx keine Chance, das Fenster neu zu zeichnen. Das kannst du auf verschiedene Arten erreichen:
- einfachste Möglichkeit: führe dort, wo die Arbeit getan wird, ab und zu ein wx.GetApp().Yield() oder wx.SafeYield() aus. Zu Risiken und Nebenwirkungen lies bitte die Dokumentation.
- erledige deine Aufgabe häppchenweise jeweils beim Feuern eines Timer-Events.
- lagere die gesamte Aufgabe in einen Thread aus und gib von dort über einen geeigneten Mechanismus (z.B. Queue) Rückmeldung über den Fortschritt.

Was von diesen Möglichkeiten für dein Programm am besten geeignet ist, lässt sich nicht allgemeingültig beantworten (hängt von der Aufgabenstellung ab) und musst du halt selbst entscheiden.

Gruß
Norbert
danx4
User
Beiträge: 2
Registriert: Dienstag 4. Januar 2011, 17:40

Hi Norbert,

mit wx.SafeYield() funktioniert es einwandfrei. Ich bin mir auch ziemlich sicher, dass ich diese Funktion noch an ein paar anderen Stellen meines Codes benötigen könnte :D.

Vielen Dank nochmal!


Gruß, David
Antworten