I'm trying to make a dialog that looks similar to the wx.MessageDialog. There's a section at the bottom that coloured different but in my code, the buttons will not cooperate.
The buttons should be aligned right, and the bottom section should expand to colour it grey. There's probably a simple solution, anyone able to see my error?
This is with the sizer set to expand:
This is with the sizer set not to expand:
Here's a working simplified version of the code which demonstrates the issue. The troublesome code is at the bottom, surrounded with "===":
import wx
class TestDialog(wx.Dialog):
def __init__(self, parent, msg, title):
wx.Dialog.__init__(self, parent, id=-1, title=title)
# outer sizer, this is to allow a spot at the bottom for the buttons
outerSizer = wx.BoxSizer(wx.VERTICAL)
# Main sizer for the message dialog
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
staticIcon = wx.StaticBitmap(self, bitmap=wx.ArtProvider.GetBitmap(wx.ART_INFORMATION), size=(32,32))
mainSizer.Add(staticIcon, flag=wx.ALL, border=10)
# Sizer to hold the message and buttons
controlsSizer = wx.BoxSizer(wx.VERTICAL)
# Static text field to show the (error/warning) message on the message dialog
errorText = wx.StaticText(self, -1, msg, wx.DefaultPosition, wx.DefaultSize, 0)
errorText.Wrap(600)
# This is a sizer so we can nest it inside the controls sizer. This allows us to use multiple border flags
errorTextSizer = wx.BoxSizer(wx.HORIZONTAL)
errorTextSizer.Add(errorText, flag=wx.TOP, border=15)
# Add the error text to the controls sizer
controlsSizer.Add(errorTextSizer, flag=wx.RIGHT, border=10)
# Outer button panel, to get that slighty greyed look
outerButtonPanel = wx.Panel(self)
outerButtonPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
outerButtonPanel.SetSizer(outerButtonPanelSizer)
# Button for the "yes" option
btnYes = wx.Button(outerButtonPanel, label='Yes')
btnYes.Bind(wx.EVT_BUTTON, self.__yes)
outerButtonPanelSizer.Add(btnYes, flag=wx.ALIGN_RIGHT | wx.ALL, border=15)
# Button for the "no" option
btnNo = wx.Button(outerButtonPanel, label='No')
btnNo.Bind(wx.EVT_BUTTON, self.__no)
outerButtonPanelSizer.Add(btnNo, flag=wx.ALIGN_RIGHT | wx.RIGHT | wx.TOP | wx.BOTTOM, border=15)
outerButtonPanel.SetBackgroundColour(wx.Colour(100, 100, 100)) # find decent colour
# Add all the sizers to each other, finish up
mainSizer.Add(controlsSizer)
outerSizer.Add(mainSizer)
# ====================================================================
outerSizer.Add(outerButtonPanel, flag=wx.ALIGN_RIGHT | wx.EXPAND)
# ====================================================================
#outerSizer.Add(outerButtonPanel, flag=wx.ALIGN_RIGHT)
# ====================================================================
# Done layout
self.SetSizerAndFit(outerSizer)
self.CenterOnScreen()
def __yes(self, evt):
self.EndModal(wx.ID_YES)
def __no(self, evt):
self.EndModal(wx.ID_NO)
if __name__ == '__main__':
app = wx.App()
dlg = TestDialog(None, "test test test test test test test test test test test test test test test test", "Test Title")
val = dlg.ShowModal()
print "Dialog result: " + str(val == wx.ID_YES)
app.Exit()
At last, the solution. wx apparently doesn't approve of multiple horizontal box sizers nested together with a panel at the core. More specifically, it doesn't like it when you attempt to align something as well as set it to expand. From what I can tell, you have to nest multiple panels and vertical box sizers (with a horizontal box sizer for the buttons).
Here's the example above, but working properly. Literally, change
outerButtonPanelSizer = wx.BoxSizer(wx.VERTICAL)
to
outerButtonPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
and the whole thing breaks.
import wx
class TestDialog(wx.Dialog):
def __init__(self, parent, msg, title):
wx.Dialog.__init__(self, parent, id=-1, title=title)
# outer sizer, this is to allow a spot at the bottom for the buttons
outerSizer = wx.BoxSizer(wx.VERTICAL)
# Main sizer for the message dialog
mainSizer = wx.BoxSizer(wx.HORIZONTAL)
staticIcon = wx.StaticBitmap(self, bitmap=wx.ArtProvider.GetBitmap(wx.ART_INFORMATION), size=(32,32))
mainSizer.Add(staticIcon, flag=wx.ALL, border=10)
# Sizer to hold the message and buttons
controlsSizer = wx.BoxSizer(wx.VERTICAL)
# Static text field to show the (error/warning) message on the message dialog
errorText = wx.StaticText(self, -1, msg, wx.DefaultPosition, wx.DefaultSize, 0)
errorText.Wrap(600)
# This is a sizer so we can nest it inside the controls sizer. This allows us to use multiple border flags
errorTextSizer = wx.BoxSizer(wx.HORIZONTAL)
errorTextSizer.Add(errorText, flag=wx.TOP, border=15)
# Add the error text to the controls sizer
controlsSizer.Add(errorTextSizer, flag=wx.RIGHT, border=10)
# Outer button panel, to get that slighty greyed look
outerButtonPanel = wx.Panel(self)
outerButtonPanelSizer = wx.BoxSizer(wx.VERTICAL)
outerButtonPanel.SetSizer(outerButtonPanelSizer)
# inner panel for the buttons (this allows us to right align the buttons
innerButtonPanel = wx.Panel(outerButtonPanel)
innerButtonPanelSizer = wx.BoxSizer(wx.HORIZONTAL)
# Button for the "yes" option
btnYes = wx.Button(innerButtonPanel, label='Yes')
btnYes.Bind(wx.EVT_BUTTON, self.__yes)
innerButtonPanelSizer.Add(btnYes, flag=wx.ALL, border=15)
# Button for the "no" option
btnNo = wx.Button(innerButtonPanel, label='No')
btnNo.Bind(wx.EVT_BUTTON, self.__no)
innerButtonPanelSizer.Add(btnNo, flag=wx.RIGHT | wx.TOP | wx.BOTTOM, border=15)
# Add the inner button panel to the outer button panel and align it right
innerButtonPanel.SetSizer(innerButtonPanelSizer)
outerButtonPanelSizer.Add(innerButtonPanel, flag=wx.ALIGN_RIGHT)
outerButtonPanel.SetBackgroundColour(wx.Colour(100, 100, 100)) # find decent colour
# Add all the sizers to each other, finish up
mainSizer.Add(controlsSizer)
outerSizer.Add(mainSizer)
# ====================================================================
outerSizer.Add(outerButtonPanel, flag=wx.EXPAND)
# Done layout
self.SetSizerAndFit(outerSizer)
self.CenterOnScreen()
def __yes(self, evt):
self.EndModal(wx.ID_YES)
def __no(self, evt):
self.EndModal(wx.ID_NO)
if __name__ == '__main__':
app = wx.App()
dlg = TestDialog(None, "test test test test test test test test test test test test test test test test", "Test Title")
val = dlg.ShowModal()
print "Dialog result: " + str(val == wx.ID_YES)
app.Exit()