I'm trying to figure out how to align a ListBox properly. As soon as i insert the lines of ListBox, the layout transforms into a mess.
#!/usr/bin/python
# -*- coding: utf-8 -*-
import wx
oplist=[]
with open("options.txt","r") as f:
for line in f:
oplist.append(line.rstrip('\n'))
print(oplist)
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title = title, size=(200,300))
self.InitUI()
self.Centre()
self.Show()
def InitUI(self):
p = wx.Panel(self)
vbox= wx.BoxSizer(wx.VERTICAL)
self.l1 = wx.StaticText(p, label="Enter number", style=wx.ALIGN_CENTRE)
vbox.Add(self.l1, -1, wx.ALIGN_CENTER_HORIZONTAL, 200)
self.b1 = wx.Button(p, label="Buton 1")
vbox.Add(self.b1, -1, wx.ALIGN_CENTER_HORIZONTAL,100)
self.flistbox= wx.ListBox(self,choices=oplist, size=(100,100), name="Field", wx.ALIGN_CENTER_HORIZONTAL)
vbox.Add(self.flistbox, -1, wx.CENTER, 10)
p.SetSizer(vbox)
app = wx.App()
Example(None, title="BoxSizer")
app.MainLoop()
Here the outputs with and without:
The listbox is being parented to the frame by using self.
self.flistbox= wx.ListBox(
self,choices=oplist, size=(100,100), name="Field", wx.ALIGN_CENTER_HORIZONTAL)
It should be parented to the panel by using p like the other controls.
self.flistbox= wx.ListBox(
p,choices=oplist, size=(100,100), name="Field", wx.ALIGN_CENTER_HORIZONTAL)
Related
In my wxPython Application I have a few wx.TextCtrl input fields for a form. My problem is, some of my wx.TextCtrl input fields are uneditable, meaning I can not type in the field nor can I select text that is in the field. My parent wx.Panel in my main.py file has two children a login wx.Panel and a wx.Notebook. The wx.TextCtrls in my login work great, but the wx.TextCtrls in my wx.Notebook do not work. The following code is from my main.py file where I create my wx.Notebook and add a page:
main.py
import wx
from LoginPanel import LoginPanel
from UserView import UserView
class MyFrame(wx.Frame):
def __init__(self, parent, ID, title):
wx.Frame.__init__(self, parent, ID, title=title, size=(850,725))
# Creating Panels
self.main = wx.Panel(self)
self.mainLogin = LoginPanel(self.main,-1,addSpacers=1)
#start off showing the login panel
self.mainLogin.Show()
# Create a notebook on the panel
self.nb = wx.Notebook(self.main, 1)
#Start off hiding the Notebook until successfully logged in
self.nb.Hide()
# create the page windows as children of the notebook
self.userAdmin = UserView(parent=self.nb, ID=-1)
# add the pages to the notebook with the label to show on the tab
self.nb.AddPage(self.userAdmin, "Users")
# Bindings
self.Bind(wx.EVT_BUTTON, self.EvtLoginBtn, self.mainLogin.loginBtns.LoginBtn)
self.Bind(wx.EVT_BUTTON, self.EvtLogoutBtn, self.mainLogin.loginBtns.LogoutBtn)
# Create sizers
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
# Adding Objects to mainSizer
self.mainSizer.AddSpacer(10)
self.mainSizer.Add(self.mainLogin, 1, wx.ALL|wx.EXPAND)
self.mainSizer.Add(self.nb, 1, wx.ALL|wx.EXPAND)
# Set main sizer
self.main.SetAutoLayout(True)
self.main.SetSizer(self.mainSizer)
self.mainSizer.Fit(self.main)
self.Layout()
self.Centre(wx.BOTH)
self.Show()
def EvtLoginBtn(self,e):
self.nb.Show()
self.mainLogin.Hide()
print("Login clicked")
self.mainSizer.Layout()
def EvtLogoutBtn(self,e):
print("Logout clicked")
app = wx.App(False)
frame = MyFrame(None, -1, 'App UI')
app.MainLoop()
LoginPanel.py
import wx
from OneLblOneSingleTxt_HorzBoxSizer_Panel import OneLblOneSingleTxt_HorzBoxSizer_Panel
from LoginBtnsPanel import LoginBtnsPanel
class LoginPanel(wx.Panel):
def __init__(self, parent, ID, addSpacers):
wx.Panel.__init__(self, parent, ID)
sizer = wx.BoxSizer(wx.VERTICAL)
self.userNamePnl = OneLblOneSingleTxt_HorzBoxSizer_Panel(self,-1,
name="loginUser", lbl="Username: ", addSpacers=1)
self.passwordPnl = OneLblOneSingleTxt_HorzBoxSizer_Panel(self,-1,
name="loginPass", lbl="Password: ", addSpacers=1)
self.loginBtns = LoginBtnsPanel(self,-1)
if addSpacers == 1:
sizer.AddStretchSpacer()
sizer.Add(self.userNamePnl,0,wx.EXPAND)
sizer.AddSpacer(10)
sizer.Add(self.passwordPnl,0,wx.EXPAND)
sizer.AddSpacer(10)
sizer.Add(self.loginBtns,0,wx.EXPAND)
if addSpacers == 1:
sizer.AddStretchSpacer()
self.SetAutoLayout(True)
self.SetSizer(sizer)
sizer.Fit(self)
self.Layout()
OneLblOneSingleTxt_HorzBoxSizer_Panel.py
import wx
class OneLblOneSingleTxt_HorzBoxSizer_Panel(wx.Panel):
def __init__(self, parent, ID, name, lbl, addSpacers):
wx.Panel.__init__(self, parent, ID)
sizer = wx.BoxSizer(wx.HORIZONTAL)
lbl = wx.StaticText(self, label=lbl)
self.singleTxt = wx.TextCtrl(self, size=(140,-1))
if addSpacers==1:
sizer.AddStretchSpacer()
sizer.Add(lbl,0,wx.EXPAND)
sizer.AddSpacer(10)
sizer.Add(self.singleTxt,1,wx.EXPAND)
sizer.AddStretchSpacer()
if addSpacers==1:
sizer.AddStretchSpacer()
self.SetAutoLayout(True)
self.SetSizer(sizer)
sizer.Fit(self)
LoginBtnsPanel.py
import wx
class LoginBtnsPanel(wx.Panel):
def __init__(self, parent, ID):
wx.Panel.__init__(self, parent, ID)
sizer = wx.BoxSizer(wx.HORIZONTAL)
self.LoginBtn =wx.Button(self, label='Login')
self.LogoutBtn =wx.Button(self, label='Logout')
sizer.AddStretchSpacer()
sizer.Add(self.LoginBtn,1,wx.EXPAND)
sizer.AddSpacer(10)
sizer.Add(self.LogoutBtn,1,wx.EXPAND)
sizer.AddStretchSpacer()
self.SetAutoLayout(True)
self.SetSizer(sizer)
sizer.Fit(self)
UserView.py
import wx
from UserTable import UserGridTable
class UserView(wx.Panel):
def __init__(self, parent, ID):
wx.Panel.__init__(self, parent, ID)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.gridPnl = wx.Panel(self,-1)
self.gridPnlSizer = wx.BoxSizer(wx.HORIZONTAL)
#Grid that show current users
self.UserGrid = UserGridTable(self.gridPnl)
#Start out showing this Grid until the Add button or Edit button is clicked
self.UserGrid.Show()
self.userEntryPnl = wx.Panel(self,0)
self.userEntryPnlSizer = wx.BoxSizer(wx.VERTICAL)
self.userlbl = wx.StaticText(self.userEntryPnl, label='Username')
self.userTxt = wx.TextCtrl(self.userEntryPnl, size=(140,-1))
self.userTxt.SetModified(True)
self.userTxt.SetEditable(True)
self.passlbl = wx.StaticText(self.userEntryPnl, label='Password')
self.passTxt = wx.TextCtrl(self.userEntryPnl, size=(140,-1))
self.passTxt.SetModified(True)
self.passTxt.SetEditable(True)
self.userEntryPnlSizer.AddStretchSpacer()
self.userEntryPnlSizer.Add(self.userlbl,0,wx.EXPAND)
self.userEntryPnlSizer.AddSpacer(10)
self.userEntryPnlSizer.Add(self.userTxt,0,wx.EXPAND)
self.userEntryPnlSizer.AddSpacer(10)
self.userEntryPnlSizer.Add(self.passlbl,0,wx.EXPAND)
self.userEntryPnlSizer.AddSpacer(10)
self.userEntryPnlSizer.Add(self.passTxt,0,wx.EXPAND)
self.userEntryPnlSizer.AddStretchSpacer()
self.userEntryPnl.SetAutoLayout(True)
self.userEntryPnl.SetSizer(self.userEntryPnlSizer)
self.userEntryPnlSizer.Fit(self.userEntryPnl)
#start out hiding this panel until Add button or Edit button is clicked
self.userEntryPnl.Hide()
self.gridPnlSizer.AddStretchSpacer()
self.gridPnlSizer.Add(self.UserGrid,0,wx.EXPAND)
self.gridPnlSizer.Add(self.userEntryPnl,0,wx.EXPAND)
self.gridPnlSizer.AddStretchSpacer()
self.gridPnl.SetAutoLayout(True)
self.gridPnl.SetSizer(self.gridPnlSizer)
self.gridPnlSizer.Fit(self.gridPnl)
self.bottomBtnsPnl = wx.Panel(self,-1)
self.bottomSizer = wx.BoxSizer(wx.HORIZONTAL)
self.AddBtn = wx.Button(self.bottomBtnsPnl, label='Add')
self.EditBtn = wx.Button(self.bottomBtnsPnl, label='Edit')
self.DeleteBtn = wx.Button(self.bottomBtnsPnl, label='Delete')
self.SaveBtn = wx.Button(self.bottomBtnsPnl, label='Save')
self.AddBtn.Show()
self.EditBtn.Show()
self.DeleteBtn.Show()
self.SaveBtn.Hide()
self.Bind(wx.EVT_BUTTON, self.addBtnEnt, self.AddBtn)
self.Bind(wx.EVT_BUTTON, self.editBtnEnt, self.EditBtn)
self.Bind(wx.EVT_BUTTON, self.deleteBtnEnt, self.DeleteBtn)
self.Bind(wx.EVT_BUTTON, self.saveBtnEnt, self.SaveBtn)
self.bottomSizer.AddStretchSpacer()
self.bottomSizer.Add(self.AddBtn,0,wx.EXPAND)
self.bottomSizer.AddSpacer(10)
self.bottomSizer.Add(self.EditBtn,0,wx.EXPAND)
self.bottomSizer.AddSpacer(10)
self.bottomSizer.Add(self.DeleteBtn,0,wx.EXPAND)
self.bottomSizer.AddSpacer(10)
self.bottomSizer.Add(self.SaveBtn,0,wx.EXPAND)
self.bottomSizer.AddSpacer(10)
self.bottomSizer.AddStretchSpacer()
self.bottomBtnsPnl.SetAutoLayout(True)
self.bottomBtnsPnl.SetSizer(self.bottomSizer)
self.bottomSizer.Fit(self.bottomBtnsPnl)
self.sizer.AddSpacer(10)
self.sizer.Add(self.gridPnl,0,wx.EXPAND)
self.sizer.AddSpacer(10)
self.sizer.Add(self.bottomBtnsPnl,0,wx.EXPAND)
self.sizer.AddSpacer(10)
self.SetAutoLayout(True)
self.SetSizer(self.sizer)
self.sizer.Fit(self)
def addBtnEnt(self,e):
self.UserGrid.Hide()
self.AddBtn.Hide()
self.EditBtn.Hide()
self.DeleteBtn.Hide()
self.SaveBtn.Show()
self.userEntryPnl.Show()
self.userEntryPnl.Layout()
def editBtnEnt(self,e):
self.UserGrid.Hide()
self.AddBtn.Hide()
self.EditBtn.Hide()
self.DeleteBtn.Hide()
self.SaveBtn.Show()
self.userEntryPnl.Show()
self.userEntryPnl.Layout()
def deleteBtnEnt(self,e):
print("Delete clicked")
def saveBtnEnt(self,e):
self.userEntryPnl.Hide()
self.SaveBtn.Hide()
self.UserGrid.Show()
self.AddBtn.Show()
self.EditBtn.Show()
self.DeleteBtn.Show()
self.userEntryPnl.Layout()
UserTable.py
import wx
import wx.grid
class UserGridTable(wx.grid.Grid):
def __init__(self, parent):
wx.grid.Grid.__init__(self, parent)
self.CreateGrid(6,3)
self.SetColLabelValue(0, "ID")
self.SetColLabelValue(1, "Username")
self.SetColLabelValue(2, "Password")
self.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.EmpCellLeftClick, self)
def EmpCellLeftClick(self,e):
self.SelectRow(e.GetRow())
How do I get self.userTxt and self.passTxt to be editable where I can enter text in and select it? Thank you for any and all help!
UPDATE:
The above code is a working on Python 2.7.8
As a quick fix, change
self.userEntryPnl = wx.Panel(self, 0)
To
self.userEntryPnl = wx.Panel(self.gridPnl, -1)
gridPnl was on top of userEntryPnl although userEntryPnl was visible. Because of that you couldn't edit what was underneath gridPnl.
How do I mention size(350,450) in terms of percentages in wxpython?
# -*- coding: utf-8 -*-
# gotoclass.py
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title,
size=(390, 350))
self.InitUI()
self.Centre()
self.Show()
def InitUI(self):
panel = wx.Panel(self)
font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT)
font.SetPointSize(9)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
st1 = wx.StaticText(panel, label='Class Name')
st1.SetFont(font)
hbox1.Add(st1, flag=wx.RIGHT, border=8)
tc = wx.TextCtrl(panel)
hbox1.Add(tc, proportion=1)
vbox.Add(hbox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP, border=10)
vbox.Add((-1, 10))
panel.SetSizer(vbox)
if __name__ == '__main__':
app = wx.App()
Example(None, title='Go To Class')
app.MainLoop()
Get the screen resolution using wx.GetDisplaySize(). Compute the percentage in pixels. Set the size by self.SetSize() later, not in the constructor but before self.Show().
You can only specify the size of widgets in wxPython by pixel size. See http://wxpython.org/docs/api/wx.Size-class.html for more information. You cannot pass percentages to it. On the other hand, you can sort of do percentages with widgets inside sizers as sizers support the idea of proportion. But I don't believe that is what you really want.
I'm having two problems with my program. The code below generates two panels when it should generate 3. It generates panel1 and panel2 no problem but panel3 should be to the right of panel2 is no where to be seen. Panel1 and panel2 are split vertically I'm trying to do the same with panel2 and panel3
My second problem is how do I generate another panel below panel1 without disrupting the splitter between panel1 and panel2 and then create a splitter between panel1 and new created panel below it?
import wx
class Panels(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title)
hbox = wx.BoxSizer(wx.HORIZONTAL)
splitter = wx.SplitterWindow(self, -1)
vbox1 = wx.BoxSizer(wx.VERTICAL)
panel1 = wx.Panel(splitter, -1)
panel12 = wx.Panel(panel1, -1, style=wx.BORDER_SUNKEN)
st1 = wx.StaticText(panel12, -1, 'Panel 1', (5, 5))
vbox1.Add(panel12, 1, wx.EXPAND)
panel1.SetSizer(vbox1)
vbox2 = wx.BoxSizer(wx.VERTICAL)
panel2 = wx.Panel(splitter, -1)
panel22 = wx.Panel(panel2, -1, style=wx.BORDER_RAISED)
st2 = wx.StaticText(panel22, -1, 'Panel 2', (5, 5))
vbox2.Add(panel22, 1, wx.EXPAND)
panel2.SetSizer(vbox2)
vbox3 = wx.BoxSizer(wx.VERTICAL)
panel3 = wx.Panel(splitter, -1)
panel32 = wx.Panel(panel3, -1, style=wx.BORDER_RAISED)
st3 = wx.StaticText(panel32, -1, 'Panel 3', (5, 5))
vbox3.Add(panel32, 1, wx.EXPAND)
panel3.SetSizer(vbox3)
hbox.Add(splitter, 1, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)
self.SetSizer(hbox)
self.CreateStatusBar()
splitter.SplitVertically(panel1, panel3)
splitter.SplitVertically(panel2, panel3)
self.Centre()
self.Show(True)
def ExitApp(self, event):
self.Close()
app = wx.App()
Panels(None, -1, 'Panels')
app.MainLoop()
You have a couple options. You could nest your SplitterWindows, which is kind of confusing, but effective. Or you could use the MultiSplitterWindow widget.
For the first one, I'd do something like this:
Create a main splitter and a sub-splitter
In the sub-splitter, but the first two panels
Put the sub-splitter and the 3rd panel in the main splitter
Or some variation thereof.
EDIT: Here's one example:
import wx
########################################################################
class RandomPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent, color):
"""Constructor"""
wx.Panel.__init__(self, parent)
self.SetBackgroundColour(color)
########################################################################
class MainPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
topSplitter = wx.SplitterWindow(self)
hSplitter = wx.SplitterWindow(topSplitter)
panelOne = RandomPanel(hSplitter, "blue")
panelTwo = RandomPanel(hSplitter, "red")
hSplitter.SplitVertically(panelOne, panelTwo)
hSplitter.SetSashGravity(0.5)
panelThree = RandomPanel(topSplitter, "green")
topSplitter.SplitHorizontally(hSplitter, panelThree)
topSplitter.SetSashGravity(0.5)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(topSplitter, 1, wx.EXPAND)
self.SetSizer(sizer)
########################################################################
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Nested Splitters",
size=(800,600))
panel = MainPanel(self)
self.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
app.MainLoop()
See also might want to look at wx.SashLayoutWindow: http://www.wxpython.org/docs/api/wx.SashLayoutWindow-class.html
Problem 1:
Create a horzontal vbox sizer. Add the sizers for panel2 and panel3 to that. This will put the panel2 and panel3 next to each other. Then add the horizontal sizer to the splitter as the second item.
Problem 2:
Create another splitter and add to a sizer (I assume splitter is a widget like panel). Then create your other panel and add it to that splitter. So you end up nesting the splitter inside a sizer. (May not need sizer for that though.) Then that sizer is inside the main splitter. You may be able to add the second splitter inside the first.
with this code:
import wx
import wx.aui
class MyFrame(wx.Frame):
def __init__(self, parent, id=-1, title='wx.aui Test',
pos=wx.DefaultPosition, size=(800, 600),
style=wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
self._mgr = wx.aui.AuiManager(self)
# create several text controls
text1 = wx.TextCtrl(self, -1, 'Pane 1 - sample text',
wx.DefaultPosition, wx.Size(200,150),
wx.NO_BORDER | wx.TE_MULTILINE)
text2 = wx.TextCtrl(self, -1, 'Pane 2 - sample text',
wx.DefaultPosition, wx.Size(200,150),
wx.NO_BORDER | wx.TE_MULTILINE)
info = wx.aui.AuiPaneInfo()
info.CaptionVisible(True)
info.BottomDockable(False)
info.LeftDockable(False)
info.RightDockable(False)
info.PaneBorder(False)
info.Top()
info.Row(1)
info2 = wx.aui.AuiPaneInfo()
info2.CaptionVisible(True)
info2.BottomDockable(False)
info2.LeftDockable(False)
info2.RightDockable(False)
info2.Top()
info2.Row(2)
self._mgr.AddPane(text1, info, 'Pane Number One')
self._mgr.AddPane(text2, info2, 'Pane Number Two')
self._mgr.Update()
self.Bind(wx.EVT_CLOSE, self.OnClose)
def OnClose(self, event):
self._mgr.UnInit()
self.Destroy()
app = wx.App()
frame = MyFrame(None)
frame.Show()
app.MainLoop()
the two panes that I create are docked in the Top.
The info.Row(1) and info2.Row(2) put the two panes one after another:
_TOP_
Pane1
Pane2
Now, if I move on Pane2, this docks in the Top and this situation occurs:
_TOP_
Pane1|Pane2
I want:
1. to avoid this situation (only one pane per row!)
2. if I move, dock the pane in the bottom/top of another pane
Is this possible?
Maybe the AuiNotebook wxPython sample works for you?
import wx
import wx.aui
########################################################################
class TabPanel(wx.Panel):
"""
This will be the first notebook tab
"""
#----------------------------------------------------------------------
def __init__(self, parent):
""""""
wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
sizer = wx.BoxSizer(wx.VERTICAL)
txtOne = wx.TextCtrl(self, wx.ID_ANY, "")
txtTwo = wx.TextCtrl(self, wx.ID_ANY, "")
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(txtOne, 0, wx.ALL, 5)
sizer.Add(txtTwo, 0, wx.ALL, 5)
self.SetSizer(sizer)
class DemoPanel(wx.Panel):
"""
This will be the first notebook tab
"""
#----------------------------------------------------------------------
def __init__(self, parent):
""""""
wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY)
# create the AuiNotebook instance
nb = wx.aui.AuiNotebook(self)
# add some pages to the notebook
pages = [(TabPanel(nb), "Tab 1"),
(TabPanel(nb), "Tab 2"),
(TabPanel(nb), "Tab 3")]
for page, label in pages:
nb.AddPage(page, label)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(nb, 1, wx.EXPAND)
self.SetSizer(sizer)
########################################################################
class DemoFrame(wx.Frame):
"""
Frame that holds all other widgets
"""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, wx.ID_ANY,
"AUI-Notebook Tutorial",
size=(600,400))
panel = DemoPanel(self)
self.Show()
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = DemoFrame()
app.MainLoop()
I would like to be able to display Notebook and a TxtCtrl wx widgets in a single frame. Below is an example adapted from the wxpython wiki; is it possible to change their layout (maybe with something like wx.SplitterWindow) to display the text box below the Notebook in the same frame?
import wx
import wx.lib.sheet as sheet
class MySheet(sheet.CSheet):
def __init__(self, parent):
sheet.CSheet.__init__(self, parent)
self.SetLabelBackgroundColour('#CCFF66')
self.SetNumberRows(50)
self.SetNumberCols(50)
class Notebook(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(600, 600))
menubar = wx.MenuBar()
file = wx.Menu()
file.Append(101, 'Quit', '' )
menubar.Append(file, "&File")
self.SetMenuBar(menubar)
wx.EVT_MENU(self, 101, self.OnQuit)
nb = wx.Notebook(self, -1, style=wx.NB_BOTTOM)
self.sheet1 = MySheet(nb)
self.sheet2 = MySheet(nb)
self.sheet3 = MySheet(nb)
nb.AddPage(self.sheet1, "Sheet1")
nb.AddPage(self.sheet2, "Sheet2")
nb.AddPage(self.sheet3, "Sheet3")
self.sheet1.SetFocus()
self.StatusBar()
def StatusBar(self):
self.statusbar = self.CreateStatusBar()
def OnQuit(self, event):
self.Close()
class MyFrame(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(450, 400))
self.text = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE)
self.Center()
class MyApp(wx.App):
def OnInit(self):
frame = Notebook(None, -1, 'notebook.py')
frame.Show(True)
frame.Center()
frame2 = MyFrame(None, -1, '')
frame2.Show(True)
self.SetTopWindow(frame2)
return True
app = MyApp(0)
app.MainLoop()
Making two widgets appear on the same frame is easy, actually. You should use sizers to accomplish this.
In your example, you can change your Notebook class implementation to something like this:
class Notebook(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(600, 600))
menubar = wx.MenuBar()
file = wx.Menu()
file.Append(101, 'Quit', '' )
menubar.Append(file, "&File")
self.SetMenuBar(menubar)
wx.EVT_MENU(self, 101, self.OnQuit)
nb = wx.Notebook(self, -1, style=wx.NB_BOTTOM)
self.sheet1 = MySheet(nb)
self.sheet2 = MySheet(nb)
self.sheet3 = MySheet(nb)
nb.AddPage(self.sheet1, "Sheet1")
nb.AddPage(self.sheet2, "Sheet2")
nb.AddPage(self.sheet3, "Sheet3")
self.sheet1.SetFocus()
self.StatusBar()
# new code begins here:
# add your text ctrl:
self.text = wx.TextCtrl(self, -1, style = wx.TE_MULTILINE)
# create a new sizer for both controls:
sizer = wx.BoxSizer(wx.VERTICAL)
# add notebook first, with size factor 2:
sizer.Add(nb, 2)
# then text, size factor 1, maximized
sizer.Add(self.text, 1, wx.EXPAND)
# assign the sizer to Frame:
self.SetSizerAndFit(sizer)
Only the __init__ method is changed. Note that you can manipulate the proportions between the notebook and text control by changing the second argument of the Add method.
You can learn more about sizers from the official Sizer overview article.
You can use a splitter, yes.
Also, it makes sense to create a Panel, place your widgets in it (with sizers), and add this panel to the Frame.