I want to display a button that when I click adds to the main panel a static text that automatic adds to the BoxSizer of the panel. I have this code but dosen't work good. Anyone can help me? I am desperate. Thanks
import wx
class MyApp(wx.App):
def OnInit(self):
self.frame = MainFrame(None,title='')
self.SetTopWindow(self.frame)
self.frame.Show()
return True
class MainFrame(wx.Frame):
def __init__(self, *args, **kwargs):
super(MainFrame, self).__init__(*args, **kwargs)
#Atributos
self.panel = MainPanel(self)
self.CreateStatusBar()
#Layout
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.panel,1,wx.EXPAND)
self.SetSizer(self.sizer)
class MainPanel(wx.Panel):
def __init__(self, parent):
super(MainPanel, self).__init__(parent)
#Atributos
bmp = wx.Bitmap('./img.png',wx.BITMAP_TYPE_PNG)
self.boton = wx.BitmapButton(self,bitmap=bmp)
# Layout
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.boton)
self.SetSizer(self.sizer)
self.Bind(wx.EVT_BUTTON,self.add,self.boton)
def add(self,event):
self.sizer.Add(wx.StaticText(self,label='Testing'))
if __name__ == "__main__":
app = MyApp(False)
app.MainLoop()
If your problem is that your text initially shows up behind the button when it is clicked, you can force the sizer to update by adding a call to your Panel's Layout method.
class MainPanel(wx.Panel):
def __init__(self, parent):
super(MainPanel, self).__init__(parent)
#Atributos
bmp = wx.Bitmap('./img.png',wx.BITMAP_TYPE_PNG)
self.boton = wx.BitmapButton(self,bitmap=bmp)
# Layout
self.sizer = wx.BoxSizer(wx.HORIZONTAL)
self.sizer.Add(self.boton)
self.SetSizer(self.sizer)
self.Bind(wx.EVT_BUTTON,self.add,self.boton)
def add(self,event):
self.sizer.Add(wx.StaticText(self,label='Testing'))
self.Layout()
Related
I wrote the following code to make grid in the Pycharm. Unable to make mathematical calculations
import wx
import wx.grid as grid
class MyFrame(wx.Frame):
def __init__(self, parent, title):
super(MyFrame, self).__init__(parent, title=title, size = (600, 800))
#self.panel = wx.Panel (self)
self.panel = MyPanel(self)
class MyPanel(wx.Panel) :
def __init__(self, parent) :
super(MyPanel, self). __init__(parent)
madrid = grid.Grid(self)
madrid.CreateGrid(40, 8)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(madrid, 1 , wx.EXPAND)
self.SetSizer(sizer)
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(parent=None, title="Electrical Sizing File")
self.frame.Show()
return True
app = MyApp()
app.MainLoop()
I am trying to use window splitter to get 6 different subwindows. Three columns and two rows. So far I am trying to use nested splitters, but it is not working.
This is the code I have:
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)
vSplitter = wx.SplitterWindow(topSplitter)
panelOne = RandomPanel(vSplitter, "blue")
panelTwo = RandomPanel(vSplitter, "red")
vSplitter.SplitVertically(panelOne, panelTwo)
vSplitter.SetSashGravity(0.5)
panelThree = RandomPanel(topSplitter, "green")
topSplitter.SplitHorizontally(vSplitter, panelThree)
topSplitter.SetSashGravity(0.5)
panelFour=RandomPanel(hSplitter, "yellow")
hSplitter.SplitVertically(topSplitter, panelFour)
hSplitter.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()
For this I am just trying to get 4 subwindows not 6, and I still get an error.
You might want to check out the MultiSplitterWindow widget:
https://wxpython.org/Phoenix/docs/html/wx.lib.splitter.MultiSplitterWindow.html
It allows you to have more than two windows in a splitter window widget. I actually wrote a bit about the various splitter windows that wxPython supports over on my blog, so you might want to check that out too.
Anyway, here is a simple example that uses that widget:
import wx
from wx.lib.splitter import MultiSplitterWindow
class SplitterPanel(wx.Panel):
def __init__(self, parent, color):
"""Constructor"""
wx.Panel.__init__(self, parent)
main_sizer = wx.BoxSizer(wx.VERTICAL)
splitter = MultiSplitterWindow(self, style=wx.SP_LIVE_UPDATE)
for col in range(3):
panel = wx.Panel(splitter, size=(200, 200))
panel.SetBackgroundColour(color)
splitter.AppendWindow(panel)
main_sizer.Add(splitter, 1, wx.ALL|wx.EXPAND)
self.SetSizer(main_sizer)
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title='Splitters')
panel = wx.Panel(self)
main_sizer = wx.BoxSizer(wx.VERTICAL)
splitter_panel = SplitterPanel(panel, color='blue')
main_sizer.Add(splitter_panel, 1, wx.ALL|wx.EXPAND)
splitter_panel_two = SplitterPanel(panel, color='red')
main_sizer.Add(splitter_panel_two, 1, wx.ALL|wx.EXPAND)
panel.SetSizer(main_sizer)
self.Show()
if __name__ == '__main__':
app = wx.App(False)
frame = MainFrame()
app.MainLoop()
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.
I have two panels to which I am both adding to a single sizer at the top level, however the elements within those panels are not aligned with each other.
Here is a simple example to demonstrate what I am trying to achieve.
import wx
class MyPanel(wx.Panel):
def __init__(self, parent):
super(MyPanel, self).__init__(parent=parent)
mygridsizer = wx.GridBagSizer()
sizer = wx.BoxSizer(orient=wx.HORIZONTAL)
sizer.Add(wx.StaticText(self,label="Hello world"))
sizer.Add(wx.Button(self, label="hello"))
mygridsizer.Add(sizer, pos=(0,0))
mygridsizer.Add(wx.ComboBox(self), pos=(0,1))
self.SetSizer(mygridsizer)
class MyPanel2(wx.Panel):
def __init__(self, parent):
super(MyPanel2, self).__init__(parent=parent)
sizer = wx.BoxSizer(orient=wx.HORIZONTAL)
sizer.Add(wx.Button(self, label="non-aligned button"))
self.SetSizer(sizer)
class MainFrame(wx.Frame):
def __init__(self, parent):
super(MainFrame, self).__init__(None)
sizer = wx.GridSizer(3, 1)
panel1 = MyPanel(parent=self)
panel2 = MyPanel2(parent=self)
sizer.Add(panel1)
sizer.Add(panel2)
self.SetSizer(sizer)
if __name__ == '__main__':
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()
With the example above, what can I do to align the buttons of both the panels?
The problem is the sizer is aligning the Panels, if you want the buttons aligned you should make them part of the same sizer (not part of two Panels with their own sizers). You could also do something like this for a quick hack (essentially adding a spacer the same size as the text):
import wx
class MyPanel(wx.Panel):
def __init__(self, parent):
super(MyPanel, self).__init__(parent=parent)
mygridsizer = wx.GridBagSizer()
sizer = wx.BoxSizer(orient=wx.HORIZONTAL)
sizer.Add(wx.StaticText(self,label="Hello world"))
sizer.Add(wx.Button(self, label="hello"))
mygridsizer.Add(sizer, pos=(0,0))
mygridsizer.Add(wx.ComboBox(self), pos=(0,1))
self.SetSizer(mygridsizer)
class MyPanel2(wx.Panel):
def __init__(self, parent):
super(MyPanel2, self).__init__(parent=parent)
sizer = wx.BoxSizer(orient=wx.HORIZONTAL)
t = wx.StaticText(self,label="Hello world")
t.Hide()
t.GetSize()
sizer.Add(t.GetSize())
sizer.Add(wx.Button(self, label="non-aligned button"))
self.SetSizer(sizer)
class MainFrame(wx.Frame):
def __init__(self, parent):
super(MainFrame, self).__init__(None)
sizer = wx.GridSizer(3, 1)
panel1 = MyPanel(parent=self)
panel2 = MyPanel2(parent=self)
sizer.Add(panel1)
sizer.Add(panel2)
self.SetSizer(sizer)
if __name__ == '__main__':
app = wx.App()
frame = MainFrame(None)
frame.Show()
app.MainLoop()
This is a continuation from this question:
wxPython: Can a wx.PyControl contain a wx.Sizer?
The main topic here is using a wx.Sizer inside a wx.PyControl. I had problems Fit()ting my CustomWidget around its child widgets. That problem was solved by calling Layout() after Fit().
However, as far as I have experienced, the solution only works when the CustomWidget is a direct child of a wx.Frame. It breaks down when it becomes a child of a wx.Panel.
EDIT: Using the code below, the CustomWidget doesn't resize correctly to fit its children. I observed that this only happens when the CustomWidget (as a subclass of wx.PyControl) is a child of a wx.Panel; otherwise, if it is a direct child of a wx.Frame, it Fit()s perfectly.
Here is the code:
import wx
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent=None)
panel = Panel(parent=self)
custom = CustomWidget(parent=panel)
self.Show()
class Panel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
self.SetSize(parent.GetClientSize())
class CustomWidget(wx.PyControl):
def __init__(self, parent):
wx.PyControl.__init__(self, parent=parent)
# Create the sizer and make it work for the CustomWidget
sizer = wx.GridBagSizer()
self.SetSizer(sizer)
# Create the CustomWidget's children
text = wx.TextCtrl(parent=self)
spin = wx.SpinButton(parent=self, style=wx.SP_VERTICAL)
# Add the children to the sizer
sizer.Add(text, pos=(0, 0), flag=wx.ALIGN_CENTER)
sizer.Add(spin, pos=(0, 1), flag=wx.ALIGN_CENTER)
# Make sure that CustomWidget will auto-Layout() upon resize
self.Bind(wx.EVT_SIZE, self.OnSize)
self.Fit()
def OnSize(self, event):
self.Layout()
app = wx.App(False)
frame = Frame()
app.MainLoop()
.SetSizerAndFit(sizer) does the job. I'm not sure why a .SetSizer(sizer) then a .Fit() won't work. Any ideas?
import wx
class Frame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, parent=None)
panel = Panel(parent=self)
custom = CustomWidget(parent=panel)
self.Show()
class Panel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent=parent)
self.SetSize(parent.GetClientSize())
class CustomWidget(wx.PyControl):
def __init__(self, parent):
wx.PyControl.__init__(self, parent=parent)
# Create the sizer and make it work for the CustomWidget
sizer = wx.GridBagSizer()
self.SetSizer(sizer)
# Create the CustomWidget's children
text = wx.TextCtrl(parent=self)
spin = wx.SpinButton(parent=self, style=wx.SP_VERTICAL)
# Add the children to the sizer
sizer.Add(text, pos=(0, 0), flag=wx.ALIGN_CENTER)
sizer.Add(spin, pos=(0, 1), flag=wx.ALIGN_CENTER)
# Set sizer and fit, then layout
self.SetSizerAndFit(sizer)
self.Layout()
# ------------------------------------------------------------
# # Make sure that CustomWidget will auto-Layout() upon resize
# self.Bind(wx.EVT_SIZE, self.OnSize)
# self.Fit()
#
#def OnSize(self, event):
# self.Layout()
# ------------------------------------------------------------
app = wx.App(False)
frame = Frame()
app.MainLoop()