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()
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 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()
I want to ask is it possible to add wx.Panel with event button in wxpython? There are plenty examples how to switch panels Hide first one and show second, but they are useless for me. I want to create panel with add button. For example I have panel something like this
import wx
import wx.grid as grid
class MainPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent = parent)
class SecondPanel(wx.Panel):
def __init__(self, parent,a,b):
wx.Panel.__init__(self, parent=parent)
MyGrid=grid.Grid(self)
MyGrid.CreateGrid(a, b)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(MyGrid, 0, wx.EXPAND)
self.SetSizer(sizer)
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="test",
size=(800,600))
self.splitter = wx.SplitterWindow(self)
self.panelOne = MainPanel(self.splitter)
self.panelTwo = SecondPanel(self.splitter, 1, 1)
txtOne = wx.StaticText(self.panelOne, -1, label = "piradoba", pos = (20,10))
self.txtTwo = wx.StaticText(self.panelOne, -1, label = "", pos = (40,80))
self.txtPlace = wx.TextCtrl(self.panelOne, pos = (20,30))
button = wx.Button(self.panelOne, label = "search", pos = (40,100))
button.Bind(wx.EVT_BUTTON, self.Onbutton)
self.splitter.SplitHorizontally(self.panelOne, self.panelTwo)
self.splitter.SetMinimumPaneSize(20)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.splitter, 1, wx.EXPAND)
self.SetSizer(sizer)
def Onbutton(self, event):
var=self.txtPlace.GetValue()
if len(var) == 9 or len(var) == 11:
???????????????????????????????????????????????
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
for example now I want to add new panel with this event what can I do? and I want to create this panel with event.
I don't know if it is what you need but in this example you have:
panel with button and event
button call function in mainframe
mainframe add next panel (with grid) to boxsizer
Tested on Linux Mint + Python 2.7.4
import wx
import wx.grid as grid
class MainPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent = parent)
self.txtOne = wx.StaticText(self, -1, label = "piradoba", pos = (20,10))
self.txtPlace = wx.TextCtrl(self, pos = (20,30))
self.txtTwo = wx.StaticText(self, -1, label = "", pos = (20,40))
button = wx.Button(self, label = "search", pos = (20,70))
button.Bind(wx.EVT_BUTTON, self.onButton)
def onButton(self, event):
var=self.txtPlace.GetValue()
if len(var) == 9 or len(var) == 11:
print "???"
# MainPanel->SplitterWindow->MainFrame ( 2x GetParent() )
self.GetParent().GetParent().AddPanel()
class SecondPanel(wx.Panel):
def __init__(self, parent,a,b):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
MyGrid=grid.Grid(self)
MyGrid.CreateGrid(a, b)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(MyGrid, 0, wx.EXPAND)
self.SetSizer(sizer)
class MainFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="test", size=(800,600))
self.splitter = wx.SplitterWindow(self)
self.panelOne = MainPanel(self.splitter)
self.panelTwo = SecondPanel(self.splitter, 1, 1)
self.splitter.SplitHorizontally(self.panelOne, self.panelTwo)
self.splitter.SetMinimumPaneSize(20)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.splitter, 2, wx.EXPAND)
self.SetSizer(self.sizer)
def AddPanel(self):
self.newPanel = SecondPanel(self, 1, 1)
self.sizer.Add(self.newPanel, 1, wx.EXPAND)
self.sizer.Layout()
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
When creating wx.ComboBox under Windows you can specify wxCB_READONLY to let users select from only proposed options. But you can clear selection by:
combo.SetSelection(wx.NOT_FOUND)
But under linux (wxGTK) the option is deselected on creation, but once selected in cannot be cleared. Not by any of following:
combo.SetSelection(wx.NOT_FOUND)
combo.SetValue('')
Is it possible to do this anyhow?
Actually, setting the value to an empty string works for me on Arch Linux:
import wx
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
choices = ["", "1", "2", "3"]
self.choices = choices
self.cbo = wx.ComboBox(self, value="1", choices=choices)
btn = wx.Button(self, label="Reset")
btn.Bind(wx.EVT_BUTTON, self.onReset)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.cbo, 0, wx.ALL, 5)
sizer.Add(btn, 0, wx.ALL, 5)
self.SetSizer(sizer)
#----------------------------------------------------------------------
def onReset(self, event):
""""""
print "resetting"
self.cbo.SetValue("")
########################################################################
class MyFrame(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="CombBox")
panel = MyPanel(self)
self.Show()
if __name__ == "__main__":
app = wx.App(False)
frame = MyFrame()
app.MainLoop()
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()