Full-disclosure: I am new to wxpython (about 3 days) and I don't really understand the finer points of boxsizers.
I'm writing a GUI to display a photo and some associated details about it. I am using box sizers to display 3 "sections" horizontally on the main tab. The leftmost item is an image preview, the middle item displays some info, and the rightmost has a StaticText title and two radio buttons. Somehow the StaticText appears to be escaping its BoxSizer. I've colored the different sections garish colors to make it more obvious:
Here's the relevant section of code:
class MainPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
self.loadContents()
def loadContents(self):
self.loadPreview()
self.loadImageInfo()
self.loadColorOptions()
row0 = wx.BoxSizer(wx.HORIZONTAL)
row0.Add(self.preview, 1, wx.LEFT, 5)
row0.Add(self.imageInfo, 1, wx.EXPAND , 5)
row0.Add(self.colorPanel, 1, wx.EXPAND, 5)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(row0)
self.SetSizer(sizer)
def loadColorOptions(self):
panel = wx.Panel(self)
panel.SetBackgroundColour((230,230,230))
self.title = wx.StaticText(self, label="Options", style=wx.TE_READONLY | wx.TE_MULTILINE)
self.radioButtonColor = wx.RadioButton(panel, label="Color", style=wx.RB_GROUP)
self.radioButtonGray = wx.RadioButton(panel, label="Grayscale")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.title, 0, wx.ALL | wx.EXPAND, 5)
sizer.Add(self.radioButtonColor, 0, wx.ALL, 5)
sizer.Add(self.radioButtonGray, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.colorPanel = panel
And the full context:
import wx
from wx.lib.wordwrap import wordwrap
import os
from mock_utils import *
ICON_STR = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'flower.ico')
INITIAL_SIZE_X = 1000
INITIAL_SIZE_Y = 700
SCALE_RATIO = 100
PREVIEW_SIZE = [4*SCALE_RATIO, 3*SCALE_RATIO] # 4:3
TITLE="Photo GUI"
class MainPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
self.loadContents()
def loadContents(self):
self.loadPreview()
self.loadImageInfo()
self.loadColorOptions()
row0 = wx.BoxSizer(wx.HORIZONTAL)
row0.Add(self.preview, 1, wx.LEFT, 5)
row0.Add(self.imageInfo, 1, wx.EXPAND , 5)
row0.Add(self.colorPanel, 1, wx.EXPAND, 5)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(row0)
self.SetSizer(sizer)
def loadColorOptions(self):
panel = wx.Panel(self)
panel.SetBackgroundColour((230,230,230))
self.title = wx.StaticText(self, label="Options", style=wx.TE_READONLY | wx.TE_MULTILINE)
self.radioButtonColor = wx.RadioButton(panel, label="Color", style=wx.RB_GROUP)
self.radioButtonGray = wx.RadioButton(panel, label="Grayscale")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.title, 0, wx.ALL | wx.EXPAND, 5)
sizer.Add(self.radioButtonColor, 0, wx.ALL, 5)
sizer.Add(self.radioButtonGray, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.colorPanel = panel
def loadPreview(self):
fname = getImage()
self.imageInfo = getImageInfo(fname)
if fname is not None:
img = wx.Image(fname, wx.BITMAP_TYPE_ANY)
img = img.Scale(PREVIEW_SIZE[0],PREVIEW_SIZE[1], wx.IMAGE_QUALITY_HIGH)
else:
img = wx.Image(PREVIEW_SIZE)
self.preview = wx.StaticBitmap(self, wx.ID_ANY, wx.Bitmap(img))
def loadImageInfo(self):
imgInfo = wx.StaticText(self, style=wx.TE_READONLY | wx.TE_MULTILINE)
infoStr = wordwrap("Filename:\n" + "\t" + self.imageInfo.get("name") + \
"\nSettings:\n" + "\t" + "Exposure: " + self.imageInfo.get("exposure") + \
"\n" + "\t" + "Focus: " + self.imageInfo.get("focus"), 350, wx.ClientDC(self))
imgInfo.SetLabel(infoStr)
imgInfo.SetBackgroundColour("yellow")
self.imageInfo = imgInfo
class Panel2(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
class PhotoGuiFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, title=TITLE, size=(INITIAL_SIZE_X,INITIAL_SIZE_Y))
self.SetIcon(wx.Icon(ICON_STR, wx.BITMAP_TYPE_ICO, 16, 16))
self.Center() # center gui on screen
self.loadPanels()
def loadPanels(self):
p = wx.Panel(self)
dock = wx.Notebook(p)
main_panel = MainPanel(dock)
panel2 = Panel2(dock)
dock.AddPage(main_panel, "Tab1")
dock.AddPage(panel2, "Tab2")
sizer = wx.BoxSizer()
sizer.Add(dock, 1, wx.EXPAND)
p.SetSizer(sizer)
if __name__ == "__main__":
app = wx.App()
frame = PhotoGuiFrame().Show()
app.MainLoop()
And a bare-bones mock_utils.py if you want a minimal "working" example (will display a blank box instead of loading an image):
pth1 = "/home/wxnewbie/Desktop/gui/test/images/img"
def getImage():
return None
def getImageInfo(fname):
return {"name": pth1+"2.tif", "exposure":"1.5ms", "focus":"automatic"}
I am completely at a loss as to why the StaticText is escaping the BoxSizer. The only thing I've been able to come up with is that I need to get rid of the panel that it's attached to (in which case, do I return the sizer itself?). But I then run into the trouble of the items in the sizer disappearing entirely, so I think I'm just missing some basic bit of info about how sizers are supposed to work.
It's a classic, can't see the woods for the trees, issue.
You are placing self.title
in self
not in the panel.
This should fix the problem.
self.title = wx.StaticText(panel, label="Options", style=wx.TE_READONLY | wx.TE_MULTILINE)