creating statictext dynamically and then setting label with python - python

I'm creating table with static text with a while loop, after that I want to set labels. I'm having problem with it, because it only works with the last one. Here is my code:
import wx
class Mainframe(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
self.panel = wx.Panel(self)
def test(self,n):
while n <=5:
a = wx.StaticText(self.panel, label='bad', id=n, pos=(20,30*n))
n = n+1
return a
test(self,0)
if test(self,0).GetId()==1:
test(self,0).SetLabel('good')
if test(self,0).GetId()==5:
test(self,0).SetLabel('exelent')
if __name__=='__main__':
app = wx.App(False)
frame = Mainframe(None)
frame.Show()
app.MainLoop()

When you are returning a it is only the last control created because each time you loop it is overwritten.
Append the controls to a list and then you can access them all.
Also note that you are calling test 5 times, so you will have 5 lots of your set of statictexts created on top of each other.
import wx
class Mainframe(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
self.panel = wx.Panel(self)
ctrls = []
for n in range(6):
ctrls.append(wx.StaticText(self.panel, label='bad',
pos=(20, 30 * n)))
ctrls[1].SetLabel('good')
ctrls[5].SetLabel('excellent')
if __name__ == '__main__':
app = wx.App(False)
frame = Mainframe(None)
frame.Show()
app.MainLoop()

Related

How to switch panels in python using wxPython

I'm trying to create an App which allows the user to switch the information show using buttons. The basic idea of the code is that the user sees buttons on the left side of the screen and when the user presses "button 1", the code shows Panel1. I've made 2 buttons so far and the code for 2 panels is written as well but i can't figure out how to update my MainFrame so it show a different panel when one of the buttons is pressed.
Code:
import wx
TabNumber = 1
class ButtonPanel(wx.Panel):
def __init__(self, parent):
global TabNumber
super(ButtonPanel, self).__init__(parent, -1)
self.Tab1Button = wx.Button(self, label="TAB 1")
self.Tab1Button.Bind(wx.EVT_BUTTON, self.SwitchTab(1))
self.Tab2Button = wx.Button(self, label="TAB 2")
self.Tab2Button.Bind(wx.EVT_BUTTON, self.SwitchTab(2))
self.Sizer = wx.BoxSizer(wx.VERTICAL)
self.Sizer.Add(self.Tab1Button, wx.CENTER,0)
self.Sizer.Add(self.Tab2Button, wx.CENTER, 0)
self.SetSizer(self.Sizer)
def SwitchTab(self, tab):
def OnClick(event):
print(f"Switch to tab {tab} started")
TabNumber = tab
print(TabNumber)
return OnClick
class Panel1(wx.Panel):
def __init__(self, parent):
super(Panel1, self).__init__(parent, -1)
self.panel = wx.Panel(self)
self.text = wx.StaticText(self.panel, label="1")
class Panel2(wx.Panel):
def __init__(self, parent):
super(Panel2, self).__init__(parent, -1)
self.panel = wx.Panel(self)
self.text = wx.StaticText(self.panel, label="2")
class MainFrame(wx.Frame):
def __init__(self):
super(MainFrame, self).__init__(None, -1, "Test Application")
self.Panels = {
"Panel1": Panel1(self),
"Panel2": Panel2(self)
}
self.MySizer = wx.BoxSizer(wx.HORIZONTAL)
self.tabpanel = ButtonPanel(self)
self.MySizer.Add(self.tabpanel,wx.CENTER,0)
self.InfoPanel = self.Panels["Panel"+str(TabNumber)]
self.MySizer.Add(self.InfoPanel, wx.CENTER,0)
self.SetSizer(self.MySizer)
if __name__ == "__main__":
app = wx.App(False)
frame = MainFrame()
frame.Show()
app.MainLoop()
I was also wondering how I can adjust the ratio for the space that is given to my ButtonPanel and my InfoPanel.
As far as I can see, you are trying to do something that works like a Wizard... On the one hand, you can use wx.adv.Wizard. On the other hand, you can look at this tutorial that does something very similar and adapt it to what you need:
WXPython: How to create a generic wizard
Good luck!

wxPython ScrolledWindow not working when used in a panel

I am having trouble nesting a ScrolledWindow inside a wx.Panel.
If I create a scrolled window on its own it seems to work, however when I create it inside a wx.Panel and add the wx.Panel to the frames sizer it does not. Is there anything that I am missing?
Note:
#pa = AScrolledWindow(self) <-- if uncommented this works
pa = ScrolledWindowHolder(self) # However this does not!
import wx
class ScrolledWindowHolder(wx.Panel):
def __init__(self, parent):
super(ScrolledWindowHolder, self).__init__(parent=parent)
mysizer = wx.GridBagSizer()
self.myscrolledWindow = AScrolledWindow(self)
mysizer.Add(self.myscrolledWindow, pos=(0, 0), flag=wx.EXPAND)
self.SetSizerAndFit(mysizer)
class AScrolledWindow(wx.ScrolledWindow):
def __init__(self, parent):
super(AScrolledWindow, self).__init__(parent)
gb = wx.GridBagSizer()
self.sizer = gb
self._labels = []
for y in xrange(1, 30):
self._labels.append(wx.StaticText(self, -1, "Label #%d" % (y,)))
gb.Add(self._labels[-1], (y, 1), (1, 1))
self.SetSizer(self.sizer)
self.SetScrollRate(5, 5)
self.EnableScrolling(True, True)
class TestFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Programmatic size change')
sz = wx.BoxSizer(wx.VERTICAL)
#pa = AScrolledWindow(self)
pa = ScrolledWindowHolder(self)
sz.Add(pa, 1, wx.EXPAND)
self.SetSizer(sz)
def main():
wxapp = wx.App()
fr = TestFrame()
fr.Show(True)
wxapp.MainLoop()
if __name__ == '__main__':
main()
Not sure why but the issue appears to be with the fact that you are using a GridBagSizer with a single widget in ScrolledWindowHolder, which itself contains a GridBagSizer.
If you change ScrolledWindowHolder to use a BoxSizer it works, as expected.
class ScrolledWindowHolder(wx.Panel):
def __init__(self, parent):
super(ScrolledWindowHolder, self).__init__(parent=parent)
mysizer = wx.BoxSizer(wx.HORIZONTAL)
self.myscrolledWindow = AScrolledWindow(self)
mysizer.Add(self.myscrolledWindow, 1, wx.EXPAND,0)
self.SetSizerAndFit(mysizer)
Also, change the value of y to for y in range(1, 60): will demonstrate the scrolled window more effectively.

Elements between panels are not aligned within a sizer

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()

Embed Separate WX GUIs into Notebook Tabs

I basically have 3 separate wxPython GUIs that I would like to combine into a single application, giving each GUI its own notebook tab. I'm not really sure how to do this though and am looking for some advice. I appreciate any comments or thoughts I can get.
My idea is that it should look something like this:
import wx
import OtherFrame
class PageOne(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is a PageOne object", (20,20))
panel=OtherFrame.Panel(parent)
box = wx.BoxSizer(wx.VERTICAL)
panel.SetSizer(self,box)
panel.Layout(self, parent)
class PageTwo(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is a PageTwo object", (40,40))
class PageThree(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
t = wx.StaticText(self, -1, "This is a PageThree object", (60,60))
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Simple Notebook Example")
p = wx.Panel(self)
nb = wx.Notebook(p)
page1 = PageOne(nb)
page2 = PageTwo(nb)
page3 = PageThree(nb)
nb.AddPage(page1, "Page 1")
nb.AddPage(page2, "Page 2")
nb.AddPage(page3, "Page 3")
sizer = wx.BoxSizer()
sizer.Add(nb, 1, wx.EXPAND)
p.SetSizer(sizer)
if __name__ == "__main__":
app = wx.App()
MainFrame().Show()
app.MainLoop()
But this gives a few errors and crashes. Without the sizers under PageOne, it just puts a gray square in the top right corner, with them, it crashes.
Thanks in advance!
I assume each of your frame's have panels in them with the code you want. Just take the code for the widgets from each of those frames and put those in each of the Page classes. You'll probably have to change the parents of the widgets to "self" instead of "panel" or whatever you call them.
Then you won't be opening a frame in each of the page code base. You don't want to open a frame there. You want the page to be the parent of the widgets, not open something else up.
Thanks to your help, I got this to work for me. Since each of my other wx App had Panel classes with all the widgets I wanted, I didn't need to create classes for each page. Here's the code:
import wx
import OtherFrame1
import OtherFrame2
import OtherFrame3
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Simple Notebook Example")
p = wx.Panel(self)
nb = wx.Notebook(p)
page1 = OtherFrame1.Panel(nb)
page2 = OtherFrame2.Panel(nb)
page3 = OtherFrame3.Panel(nb)
nb.AddPage(page1, "Page 1")
nb.AddPage(page2, "Page 2")
nb.AddPage(page3, "Page 3")
sizer = wx.BoxSizer()
sizer.Add(nb, 1, wx.EXPAND)
p.SetSizer(sizer)
if __name__ == "__main__":
app = wx.App(redirect=False)
MainFrame().Show()
app.MainLoop()
Thanks for the help!

how do I get variables from one wx notebook page to a different wx notebook page?

I am wondering how one would get a variable from one page to another from a wx notebook. I am thinking there should be some way to reference a variable if I know the variable name and page id. For example if I had the following code, how would I reference variable x from panel y and vice versa
import wx
class PanelX(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
x = 3
class PanelY(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
y=4
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Main Frame", size = (500,450))
p = wx.Panel(self)
nb = wx.Notebook(p)
nb.AddPage(PanelX(nb), "Panel X")
nb.AddPage(PanelY(nb), "Panel Y")
sizer = wx.BoxSizer()
sizer.Add(nb, 1, wx.EXPAND)
p.SetSizer(sizer)
if __name__ == "__main__":
app = wx.App()
MainFrame().Show()
app.MainLoop()
The variables you're creating in your panels aren't "saved" in the class - they're a local variable used in the constructor, and discarded from memory as soon as that method's executed.
You'll have to create your variables with "self" in front of them -- self.x = 3
This will create "instance variables" - variables that have different values depending on the class instance they belong to.
You can get a page from a Notebook by using its GetPage method. Here's your example modified:
import wx
class PanelX(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.x = 3
class PanelY(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.y = 4
class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Main Frame", size = (500,450))
p = wx.Panel(self)
nb = wx.Notebook(p)
nb.AddPage(PanelX(nb), "Panel X")
nb.AddPage(PanelY(nb), "Panel Y")
sizer = wx.BoxSizer()
sizer.Add(nb, 1, wx.EXPAND)
p.SetSizer(sizer)
page = nb.GetPage(0)
print "PanelX's X value is %s" % page.x
page = nb.GetPage(1)
print "PanelY's Y value is %s" % page.y
if __name__ == "__main__":
app = wx.App()
MainFrame().Show()
app.MainLoop()

Categories

Resources