I have a window contains different kinds of controls.
class FindReplaceWindow(wx.MiniFrame):
def __init__(self, parent):
Style = wx.DEFAULT_MINIFRAME_STYLE|wx.SYSTEM_MENU|wx.CLOSE_BOX
super(FindReplaceWindow, self).__init__(parent, -1, 'Find and Replace', style = Style)
self.BackgroundColour = wx.WHITE
self.MaxSize = wx.Size(400,300)
self.MinSize = self.MaxSize
self.CenterOnParent()
self.LabelFind = wx.StaticText(self, label = 'Find')
self.LabelReplace = wx.StaticText(self, label = 'Replace')
self.LabelTransparency = wx.StaticText(self, label = 'Transparency')
self.TextFind = wx.TextCtrl(self, size = (350,20), style = wx.TE_PROCESS_TAB)
self.TextReplace = wx.TextCtrl(self, size = (350,20), style = wx.TE_PROCESS_TAB)
self.SearchDirection = wx.RadioBox(self, -1, 'Search Direction',
size = (110,-1), choices = ('Up','Down'), style = wx.RA_VERTICAL)
self.SearchMode = wx.RadioBox(self, -1, 'Search Mode',
size = (110, -1), choices = ('Text','Regex'), style = wx.RA_VERTICAL)
self.Flags = wx.CheckListBox(self, -1, wx.DefaultPosition,
(95,-1), ('Ignore Case','Whole Word(s)','Selection Only'), wx.VERTICAL)
self.ButtonFind = wx.Button(self, wx.ID_FIND, 'Find')
self.ButtonReplace = wx.Button(self, wx.ID_REPLACE, 'Replace')
self.ButtonReplaceAll = wx.Button(self, wx.ID_REPLACE_ALL, 'Replace All')
How do I switch between them using Tab button?
Take a look at the wx.TAB_TRAVERSAL flag. There's some example code here (it also includes an alternate method): http://wiki.wxpython.org/Getting%20Started#How_to_get_tabs_to_work
Related
I am using a Panel within a Frame to display images (the GUI need to switch between multiple panels and hence the hierarchy). As images should be displayed in native size I used ScrolledWindow as the panel parent. The scrolls do appear and work, but it causes the Panel to collapse to minimum size and it needs to be resized using drag&drop every time.
Is there a way around this?
Below is a reduced version of the code, which shows the problem:
import os
import wx
from wx.lib.pubsub import pub
class Edit_Panel(wx.PyScrolledWindow):
def __init__(self, parent):
super(Edit_Panel, self).__init__(parent)
# Display size
width, height = wx.DisplaySize()
self.photoMaxSize = height - 500
# Loaded image
self.loaded_image = None
# Icons
self.open_icon_id = 500
# Generate panel
self.layout()
def layout(self):
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
divider = wx.StaticLine(self, -1, style = wx.LI_HORIZONTAL)
self.main_sizer.Add(divider, 0, wx.ALL | wx.EXPAND)
self.toolbar = self.init_toolbar()
self.main_sizer.Add(self.toolbar, 0, wx.ALL)
img = wx.EmptyImage(self.photoMaxSize, self.photoMaxSize)
self.image_control = wx.StaticBitmap(self, wx.ID_ANY,
wx.BitmapFromImage(img))
self.main_sizer.Add(self.image_control, 0, wx.ALL | wx.CENTER, 5)
self.image_label = wx.StaticText(self, -1, style = wx.ALIGN_CENTRE)
self.main_sizer.Add(self.image_label, 0, wx.ALL | wx.ALIGN_CENTRE, 5)
self.SetSizer(self.main_sizer)
fontsz = wx.SystemSettings.GetFont(wx.SYS_SYSTEM_FONT).GetPixelSize()
self.SetScrollRate(fontsz.x, fontsz.y)
self.EnableScrolling(True, True)
def init_toolbar(self):
toolbar = wx.ToolBar(self)
toolbar.SetToolBitmapSize((16, 16))
open_ico = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, (16, 16))
open_tool = toolbar.AddSimpleTool(self.open_icon_id, open_ico, "Open", "Open an Image Directory")
handler = self.on_open_reference
self.Bind(event = wx.EVT_MENU, handler = handler, source = open_tool)
toolbar.Realize()
return toolbar
def on_open_reference(self, event, wildcard = None):
if wildcard is None:
wildcard = self.get_wildcard()
defaultDir = '~/'
dbox = wx.FileDialog(self, "Choose an image to display", defaultDir = defaultDir, wildcard = wildcard, style = wx.OPEN)
if dbox.ShowModal() == wx.ID_OK:
file_name = dbox.GetPath()
# load image
self.load_image(image = file_name)
dbox.Destroy()
def get_wildcard(self):
wildcard = 'Image files (*.jpg;*.png;*.bmp)|*.png;*.bmp;*.jpg;*.jpeg'
return wildcard
def load_image(self, image):
self.loaded_image = image
# Load image
img = wx.Image(image, wx.BITMAP_TYPE_ANY)
# Label image name
image_name = os.path.basename(image)
self.image_label.SetLabel(image_name)
# scale the image, preserving the aspect ratio
scale_image = True
if scale_image:
W = img.GetWidth()
H = img.GetHeight()
if W > H:
NewW = self.photoMaxSize
NewH = self.photoMaxSize * H / W
else:
NewH = self.photoMaxSize
NewW = self.photoMaxSize * W / H
img = img.Scale(NewW, NewH)
self.image_control.SetBitmap(wx.BitmapFromImage(img))
# Render
self.main_sizer.Layout()
self.main_sizer.Fit(self)
self.Refresh()
pub.sendMessage("resize", msg = "")
class Viewer_Frame(wx.Frame):
def __init__(self, parent, id, title):
super(Viewer_Frame, self).__init__(parent = parent, id = id, title = title)
# Edit panel
self.edit_panel = Edit_Panel(self)
# Default panel
self.main_panel = self.edit_panel
# Render frame
self.render_frame()
# Subscription to re-render
pub.subscribe(self.resize_frame, ("resize"))
def render_frame(self):
# Main Sizer
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
# Add default sizer
self.main_sizer.Add(self.main_panel, 1, wx.EXPAND)
# Render
self.SetSizer(self.main_sizer)
self.Show()
self.main_sizer.Fit(self)
self.Center()
def resize_frame(self, msg):
self.main_sizer.Fit(self)
if __name__ == "__main__":
app = wx.App(False)
frame = Viewer_Frame(parent = None, id = -1, title = 'Toolkit')
app.MainLoop()
You're calling Fit(), so you're explicitly asking the panel to fit its contents, but you don't specify the min/best size of this contents anywhere (AFAICS, there is a lot of code here, so I could be missing something).
If you want to use some minimal size for the panel, just set it using SetMinSize().
I am almost done my wxPython soundboard and want to implement one quick feature.
How does one add another panel to a wxPython window, and how do you implement the text, [ NOW PLAYING ] within that panel.
Here is my code so far:
import wx
import os
import pygame
pygame.init()
##SOUNDS##
##SOUNDS##
class windowClass(wx.Frame):
__goliathwav = pygame.mixer.Sound("goliath.wav")
__channelopen = pygame.mixer.Sound("channelopen.wav")
def __init__(self, *args, **kwargs):
super(windowClass,self).__init__(*args,**kwargs)
self.__basicGUI()
def __basicGUI(self):
panel = wx.Panel(self)
menuBar = wx.MenuBar()
fileButton = wx.Menu()
aboutButton = wx.Menu()
exitItem = fileButton.Append(wx.ID_EXIT, 'Exit','status msg...')
aboutItem = aboutButton.Append(wx.ID_ABOUT, "About")
menuBar.Append(fileButton, 'File')
menuBar.Append(aboutButton, 'About this program')
self.SetMenuBar(menuBar)
self.Bind(wx.EVT_MENU, self.__quit, exitItem)
self.Bind(wx.EVT_MENU, self.__onmenuhelpabout, aboutItem)
self.__sound_dict = { "Goliath" : self.__goliathwav,
"Goliath2" : self.__channelopen
}
self.__sound_list = sorted(self.__sound_dict.keys())
self.__list = wx.ListBox(panel,pos=(20,20), size=(250,150))
for i in self.__sound_list:
self.__list.Append(i)
self.__list.Bind(wx.EVT_LISTBOX,self.__on_click)
textarea = wx.TextCtrl(self, -1,
style=wx.TE_MULTILINE|wx.BORDER_SUNKEN|wx.TE_READONLY|
wx.TE_RICH2, size=(250,150))
self.usertext = textarea
#self.__list2 = wx.ListBox(panel,pos=(19.5,180), size=(251,21)) #second panel
#for j in self.__sound_list:
# self.__list2.Append(i)
#self.__list2.Bind(wx.EVT_LISTBOX,self.__on_click)
#wx.TextCtrl(panel,pos=(10,10), size=(250,150))
self.SetTitle("Soundboard")
self.Show(True)
def __onmenuhelpabout(self,event):
dialog = wx.Dialog(self, -1, "[Soundboard]") # ,
#style=wx.DIALOG_MODAL | wx.STAY_ON_TOP)
dialog.SetBackgroundColour(wx.WHITE)
panel = wx.Panel(dialog, -1)
panel.SetBackgroundColour(wx.WHITE)
panelSizer = wx.BoxSizer(wx.VERTICAL)
boldFont = wx.Font(panel.GetFont().GetPointSize(),
panel.GetFont().GetFamily(),
wx.NORMAL,wx.BOLD)
lab1 = wx.StaticText(panel, -1, " SOUNDBOARD ")
lab1.SetFont(wx.Font(36,boldFont.GetFamily(), wx.ITALIC, wx.BOLD))
lab1.SetSize(lab1.GetBestSize())
imageSizer = wx.BoxSizer(wx.HORIZONTAL)
imageSizer.Add(lab1, 0, wx.ALL | wx.ALIGN_CENTRE_VERTICAL, 5)
lab2 = wx.StaticText(panel, -1, "Created by youonlylegoonce(cyrex)(Kommander000) for the glory " + \
"of the republic.")
panelSizer.Add(imageSizer, 0, wx.ALIGN_CENTRE)
panelSizer.Add((10, 10)) # Spacer.
panelSizer.Add(lab2, 0, wx.ALIGN_CENTRE)
panel.SetAutoLayout(True)
panel.SetSizer(panelSizer)
panelSizer.Fit(panel)
topSizer = wx.BoxSizer(wx.HORIZONTAL)
topSizer.Add(panel, 0, wx.ALL, 10)
dialog.SetAutoLayout(True)
dialog.SetSizer(topSizer)
topSizer.Fit(dialog)
dialog.Centre()
btn = dialog.ShowModal()
dialog.Destroy()
def __on_click(self,event):
event.Skip()
name = self.__sound_list[self.__list.GetSelection()]
sound = self.__sound_dict[name]
print("[ NOW PLAYING ] ... %s" % name)
pygame.mixer.Sound.play(sound)
def __quit(self, e):
self.Close()
def main():
app = wx.App()
windowClass(None, -1, style=wx.MAXIMIZE_BOX | wx.CAPTION | wx.CENTRE)
app.MainLoop()
main()
Before:
print("[ NOW PLAYING ] ... %s" % name)
input:
self.usertext.SetValue("[ NOW PLAYING ] ... %s" % name)
P.S. Your indentation is a mess
I'm trying to use wx Python's AGW LabelBook (using wxPython 2.8.11.0, Python 2.7.1+, Ubuntu 11.04), such that the tabs (list) are left-aligned; here I have some short texts, and I expected the tablist area would have its width shortened accordingly; but instead I get this:
At that mouse position, I get a sizer pointer - and I can drag it to the right to increase the width of the tablist area as much as I want; but I cannot drag it any further to the left, to make the width shorter. I also tried to use INB_FIT_LABELTEXT, but it doesn't seem to change anything...
Is it possible to somehow instruct LabelBook to set the minimal width of the left tablist area to the approx width of text (say, indicated at the drawn red line)?
This is the code I used to generate the screenshot:
import wx
import wx.lib.agw
import wx.lib.agw.labelbook as LB
from wx.lib.agw.fmresources import *
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "Labelbook test")
self.tlbook = LB.LabelBook(self, -1, size=(400, 200), style = wx.NB_LEFT, agwStyle = INB_LEFT | INB_FIT_LABELTEXT | INB_FIT_BUTTON | INB_SHOW_ONLY_TEXT | INB_USE_PIN_BUTTON)
sizer_1 = wx.BoxSizer(wx.VERTICAL)
self.tlbook_panel_1 = wx.Panel(self.tlbook)
self.tlbook_panel_2 = wx.Panel(self.tlbook)
self.tlbook.AddPage(self.tlbook_panel_1, "Test 1")
self.tlbook.AddPage(self.tlbook_panel_2, "Test 2")
sizer_1.Add(self.tlbook, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.SetSize((450, 250))
self.Layout()
app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()
Ok, I think I got it:
... and the thing is, that the width of the tab area is hardcoded in the source for LabelBook as 100 pixels, but not all in the same class - so some monkeypatching is required, if one wants to leave the source in tact. Here is the code:
import wx
import wx.lib.agw
import wx.lib.agw.labelbook as LB
#~ from wx.lib.agw.labelbook import * # for INB_BOLD_TAB_SELECTION = 16384? nope
INB_BOLD_TAB_SELECTION = 16384
from wx.lib.agw.fmresources import *
WIDTHLIMITPIX=20
class OLabelContainer(LB.LabelContainer): # overloaded version
def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, agwStyle=0, name="LabelContainer"):
super(OLabelContainer, self).__init__(parent, id, pos, size, style, agwStyle, name)
def Resize(self, event): # copy from wx/lib/agw/labelbook.py
# Resize our size
self._tabAreaSize = self.GetSize()
newWidth = self._tabAreaSize.x
x = event.GetX()
if self.HasAGWFlag(INB_BOTTOM) or self.HasAGWFlag(INB_RIGHT):
newWidth -= event.GetX()
else:
newWidth = x
# hack: was 100 here
if newWidth < WIDTHLIMITPIX: #100: # Dont allow width to be lower than that
newWidth = WIDTHLIMITPIX #100
self.SetSizeHints(newWidth, self._tabAreaSize.y)
# Update the tab new area width
self._nTabAreaWidth = newWidth
self.GetParent().Freeze()
self.GetParent().GetSizer().Layout()
self.GetParent().Thaw()
LB.LabelContainer = OLabelContainer # do monkeypatch old class
class MyLabelBook(LB.LabelBook):
def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, size=wx.DefaultSize, style=0, agwStyle=0, name="LabelBook"):
super(MyLabelBook, self).__init__(parent, id, pos, size, style, agwStyle, name)
self._fontSizeMultiple = 1.0
self._fontBold = False
print(self._pages) # is OLabelContainer, OK
def GetFontBold(self): # copy from wx/lib/agw/labelbook.py
return self._fontBold
def ResizeTabArea(self): # copy from wx/lib/agw/labelbook.py
agwStyle = self.GetAGWWindowStyleFlag()
if agwStyle & INB_FIT_LABELTEXT == 0:
return
if agwStyle & INB_LEFT or agwStyle & INB_RIGHT:
dc = wx.MemoryDC()
dc.SelectObject(wx.EmptyBitmap(1, 1))
font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
font.SetPointSize(font.GetPointSize()*self._fontSizeMultiple)
if self.GetFontBold() or agwStyle & INB_BOLD_TAB_SELECTION:
font.SetWeight(wx.FONTWEIGHT_BOLD)
dc.SetFont(font)
maxW = 0
for page in xrange(self.GetPageCount()):
caption = self._pages.GetPageText(page)
w, h = dc.GetTextExtent(caption)
maxW = max(maxW, w)
maxW += 24 #TODO this is 6*4 6 is nPadding from drawlabel
if not agwStyle & INB_SHOW_ONLY_TEXT:
maxW += self._pages._nImgSize * 2
maxW = max(maxW, WIDTHLIMITPIX) # hack: was 100 here
self._pages.SetSizeHints(maxW, -1)
self._pages._nTabAreaWidth = maxW
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "Labelbook test")
self.tlbook = MyLabelBook(self, -1, size=(400, 200), style = wx.NB_LEFT, agwStyle = INB_LEFT | INB_FIT_LABELTEXT | INB_FIT_BUTTON | INB_SHOW_ONLY_TEXT | INB_USE_PIN_BUTTON)
sizer_1 = wx.BoxSizer(wx.VERTICAL)
self.tlbook_panel_1 = wx.Panel(self.tlbook)
self.tlbook_panel_2 = wx.Panel(self.tlbook)
self.tlbook.AddPage(self.tlbook_panel_1, "Test 1")
self.tlbook.AddPage(self.tlbook_panel_2, "Test 2")
sizer_1.Add(self.tlbook, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.SetSize((450, 250))
self.Layout()
app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()
As pointed out in some other topics, wx.MessageDialog doesn't respond to many API functions, such as an external call from Destroy(), etc. So there is a need for building a wx.GenericMessageBox derived from wx.Dialog.
Here it is :
import wx
class GenericMessageBox(wx.Dialog):
def __init__(self, parent, text, title = ''):
wx.Dialog.__init__(self, parent, -1, title = title, size = (360,120), style = wx.DEFAULT_DIALOG_STYLE)
panel = wx.Panel(self, wx.ID_ANY, size = (360, 50), pos = (0,0))
panel.SetBackgroundColour('#FFFFFF')
label = wx.StaticText(panel, -1, text, pos = (50,20))
panel2 = wx.Panel(self, wx.ID_ANY, size = (360, 40), pos = (0, 50))
btn = wx.Button(panel2, wx.ID_OK, pos = (250,7))
self.ShowModal()
app = wx.App()
frame = wx.Frame(None, 0, 'Test')
frame.Show()
GenericMessageBox(frame, 'This is a message box that is derived from wx.Dialog. You can Destroy() it from anywhere in the code.', 'Test')
app.MainLoop()
Unlike wx.lib.agw.genericmessagedialog, this one's goal is to have the closest look possible to native OS look (here Windows look). [genericmessagedialog has pictures in the buttons, which is not like Windows' native look]
How would it be possible to improve this dialog in order that it its size is automatically increased if StaticText needs two lines?
Moreover the OK button (x,y) positionning is okay and centered on the grey panel on my machine, but would it be the same on other platforms?
(I think such a snippet could be useful for community.)
To manage the Layout, it is better to use Sizer instead of position.
You can have a try with following code:
use self.setMessageLine(Num) to set the output to see the difference.
import wx
class MyDialog ( wx.Dialog ):
def __init__( self, parent ):
wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = wx.EmptyString, pos = wx.DefaultPosition, size = wx.Size( 300,200 ), style = wx.DEFAULT_DIALOG_STYLE )
#set the minimum Size of the frame to Fit()
self.SetSizeHintsSz( wx.Size( 300,-1 ), wx.DefaultSize )
fgSizer = wx.FlexGridSizer( 2, 1, 0, 0 )
fgSizer.AddGrowableCol( 0 )
fgSizer.AddGrowableRow( 0 )
fgSizer.SetFlexibleDirection( wx.BOTH )
fgSizer.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_ALL )
self.m_panel = wx.Panel( self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.SIMPLE_BORDER|wx.TAB_TRAVERSAL )
gSizer = wx.GridSizer( 1, 1, 0, 0 )
self.m_staticText = wx.StaticText( self.m_panel, wx.ID_ANY, u"test", wx.DefaultPosition, wx.DefaultSize, 0 )
self.m_staticText.Wrap( 10 )
gSizer.Add( self.m_staticText, 0, wx.ALIGN_CENTER|wx.ALL, 5 )
self.m_panel.SetSizer( gSizer )
self.m_panel.Layout()
gSizer.Fit( self.m_panel )
fgSizer.Add( self.m_panel, 1, wx.EXPAND |wx.ALL, 5 )
m_sdbSizer = wx.StdDialogButtonSizer()
self.m_sdbSizerOK = wx.Button( self, wx.ID_OK )
m_sdbSizer.AddButton( self.m_sdbSizerOK )
self.m_sdbSizerCancel = wx.Button( self, wx.ID_CANCEL )
m_sdbSizer.AddButton( self.m_sdbSizerCancel )
m_sdbSizer.Realize()
fgSizer.Add( m_sdbSizer, 1, wx.ALL|wx.EXPAND, 5 )
self.SetSizer( fgSizer )
self.Layout()
self.Centre( wx.BOTH )
self.setMessageLine(10)
def setMessageLine(self, messageLine):
msg = ""
for i in range(0, messageLine):
msg += "Line %d \n" % i
self.m_staticText.SetLabel(msg)
self.Fit()
if __name__ == '__main__':
app = wx.App()
dlg = MyDialog(None)
dlg.ShowModal()
app.MainLoop()
pass
I have a panel to control editing of a matplotlib graph in a wxPython frame. The wxPython install was recently updated to 2.8.12.1 from 2.6.4.0 and it broke a few things, namely, the scroll panel no longer fills a block but instead stays at a minimum size. I'm just now picking this up from a year ago so I'm a bit rusty. Any help would be much appreciated!
Below is a stripped-down version of the code that can be run on its own and displays the problem. The ScrolledWindow should expand up to 400px. When I run it self.scroll.GetSize() returns (292, 257) but it clearly is not displaying at that size.
# testing scroll panel for PlotEditFrame
import wx
# spoof the necessary matplotlib objects
class FakePlot:
def __init__(self):
self.figure = FakeFigure()
def get_figure(self):
return self.figure
class FakeFigure:
def __init__(self):
self.axes = [FakeAxis() for i in range(0,2)]
class FakeAxis:
def __init__(self):
self.lines = [FakeLine(i) for i in range(0, 4)]
class FakeLine:
def __init__(self,i):
self.label = "line #%s"%i
def get_label(self):
return self.label
class PlotEditFrame(wx.Frame):
"""
This class holds the frame for plot editing tools
"""
def __init__(self, parent, plot):
"""Constructor for PlotEditFrame"""
wx.Frame.__init__(self, parent, -1, "Edit Plot")
self.parent = parent
self.plot = plot
self.figure = plot.get_figure()
self.advanced_options = None
self.scroll = wx.ScrolledWindow(self, -1)
self.InitControls()
def InitControls(self):
"""Create labels and controls based on the figure's attributes"""
# Get current axes labels
self.lineCtrls = [( wx.StaticText(self.scroll, -1, "Column:"),
wx.StaticText(self.scroll, -1, "Color:"),
wx.StaticText(self.scroll, -1, ""))]
for axis in self.figure.axes:
for line in axis.lines:
color = wx.Colour(255,0,0,0)
lineTxt = wx.TextCtrl(self.scroll, -1, line.get_label(), size=(175,-1))
lineColor = wx.TextCtrl(self.scroll, -1, "#%02x%02x%02x"%color.Get())
lineBtn = wx.Button(self.scroll, -1, size=(25,25))
lineBtn.SetBackgroundColour(color)
self.lineCtrls.append((lineTxt, lineColor, lineBtn))
# Place controls
boxSizer = wx.BoxSizer(wx.VERTICAL)
lineBox = wx.StaticBox(self, -1, "Lines")
lineBoxSizer = wx.StaticBoxSizer(lineBox, wx.VERTICAL)
lineSizer = wx.FlexGridSizer(rows=len(self.lineCtrls)+1, cols=4, vgap=3, hgap=3)
for ctrls in self.lineCtrls:
lineSizer.AddMany([(ctrls[0], 0, wx.ALIGN_LEFT | wx.EXPAND),
(ctrls[1], 0, wx.ALIGN_LEFT),
(ctrls[2], 0, wx.ALIGN_CENTER| wx.FIXED_MINSIZE),
((3,3), 0, wx.ALIGN_CENTER)])
lineSizer.AddGrowableCol(0)
# Set size
self.scroll.SetSizer(lineSizer)
width = self.scroll.GetBestSize().width
height = self.scroll.GetBestSize().height
if height > 400:
height = 400
width = width + 25 # button size
self.scroll.SetSize((width, height))
self.scroll.SetScrollbars(0, 1, 1,1)
print "set scrollbars at %s x %s"%(width, height)
lineBoxSizer.Add(self.scroll, 0, wx.EXPAND)
boxSizer.AddMany([ (lineBoxSizer, 0, wx.EXPAND) ])
self.SetSizer(boxSizer)
self.SetAutoLayout(1)
self.Fit()
height = self.GetSize().GetHeight()
self.SetSizeHints(minH=height, maxH=height,
minW=width, maxW=width*5)
if __name__ == '__main__':
app = wx.PySimpleApp(0)
parent = wx.Frame(None, wx.ID_ANY, 'test', size=(300,300))
plot = FakePlot()
panel = PlotEditFrame(parent, plot)
panel.Show()
app.MainLoop()
I can't figure out what panel needs resized. Some things I've tried, to no avail:
# These have no visible effect
boxSizer.SetMinSize((width, height))
self.scroll.SetVirtualSize((width, height))
lineBoxSizer.Fit(self.scroll)
lineBoxSizer.SetVirtualSizeHints(self.scroll)
# This makes the window the right size, but not the scroll panel
lineBoxSizer.SetMinSize((width, height))
I edited your code a bit to get it to work:
import wx
# spoof the necessary matplotlib objects
class FakePlot:
def __init__(self):
self.figure = FakeFigure()
def get_figure(self):
return self.figure
class FakeFigure:
def __init__(self):
self.axes = [FakeAxis() for i in range(0,2)]
class FakeAxis:
def __init__(self):
self.lines = [FakeLine(i) for i in range(0, 4)]
class FakeLine:
def __init__(self,i):
self.label = "line #%s"%i
def get_label(self):
return self.label
class PlotEditFrame(wx.Frame):
"""
This class holds the frame for plot editing tools
"""
def __init__(self, parent, plot, size):
"""Constructor for PlotEditFrame"""
wx.Frame.__init__(self, parent, -1, "Edit Plot", size=size)
self.parent = parent
self.plot = plot
self.figure = plot.get_figure()
self.advanced_options = None
self.scroll = wx.ScrolledWindow(self, -1)
self.InitControls()
def InitControls(self):
"""Create labels and controls based on the figure's attributes"""
# Get current axes labels
self.lineCtrls = [( wx.StaticText(self.scroll, -1, "Column:"),
wx.StaticText(self.scroll, -1, "Color:"),
wx.StaticText(self.scroll, -1, ""))]
for axis in self.figure.axes:
for line in axis.lines:
color = wx.Colour(255,0,0,0)
lineTxt = wx.TextCtrl(self.scroll, -1, line.get_label(), size=(175,-1))
lineColor = wx.TextCtrl(self.scroll, -1, "#%02x%02x%02x"%color.Get())
lineBtn = wx.Button(self.scroll, -1, size=(25,25))
lineBtn.SetBackgroundColour(color)
self.lineCtrls.append((lineTxt, lineColor, lineBtn))
# Place controls
boxSizer = wx.BoxSizer(wx.VERTICAL)
lineBox = wx.StaticBox(self, -1, "Lines")
lineBoxSizer = wx.StaticBoxSizer(lineBox, wx.VERTICAL)
lineSizer = wx.FlexGridSizer(rows=len(self.lineCtrls)+1, cols=4, vgap=3, hgap=3)
for ctrls in self.lineCtrls:
lineSizer.AddMany([(ctrls[0], 0, wx.ALIGN_LEFT | wx.EXPAND),
(ctrls[1], 0, wx.ALIGN_LEFT),
(ctrls[2], 0, wx.ALIGN_CENTER| wx.FIXED_MINSIZE),
((3,3), 0, wx.ALIGN_CENTER)])
lineSizer.AddGrowableCol(0)
# Set size
self.scroll.SetSizer(lineSizer)
width = self.scroll.GetBestSize().width
height = self.scroll.GetBestSize().height
if height > 400:
height = 400
width = width + 25 # button size
self.scroll.SetSize((width, height))
self.scroll.SetScrollbars(0, 1, 1,1)
print "set scrollbars at %s x %s"%(width, height)
lineBoxSizer.Add(self.scroll, 1, wx.EXPAND)
boxSizer.Add(lineBoxSizer, 1, wx.EXPAND)
self.SetSizer(boxSizer)
self.SetAutoLayout(1)
#self.Fit()
height = self.GetSize().GetHeight()
self.SetSizeHints(minH=height, maxH=height,
minW=width, maxW=width*5)
if __name__ == '__main__':
app = wx.App(False)
plot = FakePlot()
frame = PlotEditFrame(None, plot, size=(300,300))
frame.Show()
app.MainLoop()
The main thing was to set the proportion to "1" on the following two lines:
lineBoxSizer.Add(self.scroll, 1, wx.EXPAND)
boxSizer.Add(lineBoxSizer, 1, wx.EXPAND)
I changed the way you start the program as it's a little silly to put a frame inside another frame for this case. Also PySimpleApp is deprecated, so I changed that too. I have almost never found a good use for the "Fit()" method, so I took that out as it was squashing the initial GUI too much.
Hope that helps!