Yesterday found out that my router can be controlled by telnet, and today I was looking for some qt4,pygtk or wx to store all the router telnet commands in a gui. Less than 15 minutes ago I found this website - zetcode(dot)com/wxpython/advanced/ , which got the right information that I need. Unfortunatelly I don't understand how to include text in wx modules, because I am using it for a first time. Can you tell me how to assign text to the left window, because once I start the module it shows me a grey screen with a buttons in it's menu. The grey area that is the most left must contain around 10 telnet commands, where the "help" contains all of the commands saved in a html file.
import wx
import wx.html as html
class HelpWindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(570, 400))
toolbar = self.CreateToolBar()
toolbar.AddLabelTool(1, 'Exit', wx.Bitmap('icons/exit.png'))
toolbar.AddLabelTool(2, 'Help', wx.Bitmap('icons/help.png'))
toolbar.Realize()
self.splitter = wx.SplitterWindow(self, -1)
self.panelLeft = wx.Panel(self.splitter, -1, style=wx.BORDER_SUNKEN)
self.panelRight = wx.Panel(self.splitter, -1)
vbox2 = wx.BoxSizer(wx.VERTICAL)
header = wx.Panel(self.panelRight, -1, size=(-1, 20))
header.SetBackgroundColour('#6f6a59')
header.SetForegroundColour('WHITE')
hbox = wx.BoxSizer(wx.HORIZONTAL)
st = wx.StaticText(header, -1, 'Help', (5, 5))
font = st.GetFont()
font.SetPointSize(9)
st.SetFont(font)
hbox.Add(st, 1, wx.TOP | wx.BOTTOM | wx.LEFT, 5)
close = wx.BitmapButton(header, -1, wx.Bitmap('icons/fileclose.png', wx.BITMAP_TYPE_PNG),
style=wx.NO_BORDER)
close.SetBackgroundColour('#6f6a59')
hbox.Add(close, 0)
header.SetSizer(hbox)
vbox2.Add(header, 0, wx.EXPAND)
help = html.HtmlWindow(self.panelRight, -1, style=wx.NO_BORDER)
help.LoadPage('wx.html')
vbox2.Add(help, 1, wx.EXPAND)
self.panelRight.SetSizer(vbox2)
self.panelLeft.SetFocus()
self.splitter.SplitVertically(self.panelLeft, self.panelRight)
self.splitter.Unsplit()
self.Bind(wx.EVT_BUTTON, self.CloseHelp, id=close.GetId())
self.Bind(wx.EVT_TOOL, self.OnClose, id=1)
self.Bind(wx.EVT_TOOL, self.OnHelp, id=2)
self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPressed)
self.CreateStatusBar()
self.Centre()
self.Show(True)
def OnClose(self, event):
self.Close()
def OnHelp(self, event):
self.splitter.SplitVertically(self.panelLeft, self.panelRight)
self.panelLeft.SetFocus()
def CloseHelp(self, event):
self.splitter.Unsplit()
self.panelLeft.SetFocus()
def OnKeyPressed(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_F1:
self.splitter.SplitVertically(self.panelLeft, self.panelRight)
self.panelLeft.SetFocus()
app = wx.App()
HelpWindow(None, -1, 'HelpWindow')
app.MainLoop()
Found it...
wx.StaticText(self.panelLeft, -1, 'thetextgoeshere', (15, 5))
Related
I am using Hide() and Show() from wx to do the "next page" effect by hiding a panel and showing the next one but in the same frame (not very sure if I am doing it correctly though). At certain pages, the panel is just a small cropped version at the top left corner while some other panels can work normally (display the full thing). How do I solve this problem?
I saw something on stackoverflow about child/parent of the panel or frame and tried changing my code but it does not work, not very sure about how to do it correctly.
class MyPanel(wx.Panel):
def __init__(self, parent):
#Constructor
wx.Panel.__init__(self, parent=parent)
#self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
#This is for older versions of wx
self.frame = parent
self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)
self.Layout()
def OnEraseBackground(self, evt):
#Add background pic
#From ColourDB.py
dc = evt.GetDC()
if not dc:
dc = wx.ClientDC(self)
rect = self.GetUpdateRegion().GetBox()
dc.SetClippingRect(rect)
dc.Clear()
bmp = wx.Bitmap("RszHive.jpg")
dc.DrawBitmap(bmp, 0, 0)
class StartPage(wx.Frame):
def __init__(self, current_dt):
#Settings for frame
super().__init__(parent=None, title='Test', size=(850,790))
#setting up main panel (home page)
self.panel = MyPanel(self)
self.current_dt = current_dt
#so that frame will be in the center of the screen
self.Center()
self.vert_sizer = wx.BoxSizer(wx.VERTICAL)
from Database import DataBase, OperatingHours, GetDayTime, GetMenuByDayTime
dDataBase = DataBase("Full_Menu_Database.txt")
dOperatingHours = OperatingHours("Operating Hours.txt")
# Convert to a tuple needed for the functions
tDayTime = GetDayTime(self.get_dt())
# Function to get menu dictionary by date and time
# Will return an empty dictionary if no food/stores are available
self.stores_open = GetMenuByDayTime(dDataBase, dOperatingHours, tDayTime)
if self.stores_open == {}:
self.ophours = wx.StaticText(self.panel, -1, style=wx.ALIGN_CENTER)
self.ophours.SetLabel("Test")
self.ophours_font = wx.Font(19, wx.TELETYPE, wx.NORMAL, wx.NORMAL)
self.ophours.SetFont(self.ophours_font)
self.vert_sizer.Add(self.ophours, 0, wx.ALL | wx.CENTER, 10)
else:
self.store_names, self.stores_ = [], []
for onestorename in self.stores_open.keys():
self.store_names.append(onestorename)
self.stores_.append(self.stores_open[onestorename])
#btn for store1
store_btn1 = wx.Button(self.panel, label= self.store_names[0])
store_btn1.Bind(wx.EVT_BUTTON, self.click_store1)
self.vert_sizer.Add(store_btn1, 0, wx.ALL | wx.CENTER, 5)
#btn for store2 if have
if len(self.store_names) > 1:
store_btn2 = wx.Button(self.panel, label=self.store_names[1])
store_btn2.Bind(wx.EVT_BUTTON, self.click_store2)
self.vert_sizer.Add(store_btn2, 0, wx.ALL | wx.CENTER, 5)
# btn for store3 if have
if len(self.store_names) > 2:
store_btn3 = wx.Button(self.panel, label=self.store_names[2])
store_btn3.Bind(wx.EVT_BUTTON, self.click_store3)
self.vert_sizer.Add(store_btn3, 0, wx.ALL | wx.CENTER, 5)
# btn for store4 if have
if len(self.store_names) > 3:
store_btn4 = wx.Button(self.panel, label=self.store_names[3])
store_btn4.Bind(wx.EVT_BUTTON, self.click_store4)
self.vert_sizer.Add(store_btn4, 0, wx.ALL | wx.CENTER, 5)
# btn for store5 if have
if len(self.store_names) > 4:
store_btn5 = wx.Button(self.panel, label=self.store_names[4])
store_btn5.Bind(wx.EVT_BUTTON, self.click_store5)
self.vert_sizer.Add(store_btn5, 0, wx.ALL | wx.CENTER, 5)
self.SetSizer(self.vert_sizer)
self.Layout()
self.Show()
Picture of what the panel looks like when i run the code
#igor is correct a call to Layout will get the job done.
Here is an example:
Click on the displayed panel to swap to the other one.
import wx
class MyPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
self.panel = wx.Panel(self)
self.btn = wx.Button(self.panel, label="Panel 1", size=(250,75))
self.btn.Bind(wx.EVT_BUTTON, self.switch)
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox1.Add(self.btn)
self.panel.SetSizer(vbox1)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.panel)
self.SetSizer(vbox)
self.Show()
def switch(self, event):
self.parent.Swap()
class MyOtherPanel(wx.Panel):
def __init__(self, parent):
super().__init__(parent)
self.parent = parent
self.panel = wx.Panel(self)
self.btn = wx.Button(self.panel, label="Panel 2", size=(175,250))
self.btn.Bind(wx.EVT_BUTTON, self.switch)
vbox1 = wx.BoxSizer(wx.VERTICAL)
vbox1.Add(self.btn)
self.panel.SetSizer(vbox1)
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.panel)
self.SetSizer(vbox)
self.Show()
self.panel.Hide()
def switch(self, event):
self.parent.Swap()
class PanelSwitcher(wx.Frame):
def __init__(self):
super().__init__(None)
vbox = wx.BoxSizer(wx.VERTICAL)
self.panel1 = MyPanel(self)
self.panel2 = MyOtherPanel(self)
vbox.Add(self.panel1)
vbox.Add(self.panel2)
self.SetSizer(vbox)
self.Show()
def Swap(self):
if self.panel1.panel.IsShown():
self.panel1.panel.Hide()
self.panel2.panel.Show()
else:
self.panel2.panel.Hide()
self.panel1.panel.Show()
self.Layout()
if __name__ == "__main__":
app = wx.App()
PanelSwitcher()
app.MainLoop()
I also had the problem a very long time and did not know the solution. The sizers did not work (as I expected)
For me, the problem was, that the panel had no (or the incorrect size). The solution was eiter:
panel.Fit()
or
panel.SetSize(x,y)
Another possibility was, to first add the panel into a sizer. And then set them to the frame.
Afterwards put the buttons into the sizer - and add them to the panel.
This also solves the incorrect size of the panel.
I am trying to add text and a link in the same line. Looking to internet I have only found either statictext (that will allow the text) and wx.adv.HyperlinkCtrl which only adds a link. Ideally if I can link them both in a single sentence will be ideal.
How I can do that?
Can't you just bundle them together with a sizer?
e.g.
#!/usr/bin/python
import wx
import wx.lib.agw.hyperlink as hl
class Example(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title)
self.InitUI()
def InitUI(self):
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
text_sizer = wx.BoxSizer(wx.HORIZONTAL)
textS = wx.StaticText(panel, label='Plain')
textS.SetFont(wx.Font(9, wx.SWISS, wx.NORMAL, wx.BOLD, False, 'Arial'))
lnk = hl.HyperLinkCtrl(panel, -1, "wxPython Main Page",
URL="http://www.wxpython.org/")
textE = wx.StaticText(panel, label='Text')
textE.SetFont(wx.Font(12, wx.SWISS, wx.ITALIC, wx.NORMAL, False, 'Courier'))
self.SetSize((500, 150))
text_sizer.Add(textS, 0, wx.ALIGN_CENTRE|wx.ALL, 0 )
text_sizer.Add(lnk, 0, wx.ALL, 0 )
text_sizer.Add(textE, 0, wx.ALL, 0 )
sizer.Add(text_sizer)
lnk.EnableRollover(True)
lnk.SetToolTip(wx.ToolTip("Hello World!"))
lnk.UpdateLink()
self.SetSizer(sizer)
self.Centre()
self.Show(True)
if __name__ == '__main__':
ex = wx.App()
Example(None, 'A Hyperlink')
ex.MainLoop()
I'm looking for a way to get a list of all sizerItems which correspond to widgets. To demonstrate, I created the following example:
import wx
from wx.lib.scrolledpanel import ScrolledPanel
class Tester(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Window")
self.panel = ScrolledPanel(parent=self, id=-1)
self.panel.SetupScrolling()
self.sizerItems = []
Btn1 = wx.Button(self.panel, -1, "I'm a Button!")
Btn2 = wx.Button(self.panel, -1, "Me Too!")
Btn3 = wx.Button(self.panel, -1, "Hey! Quiet up there!")
Btn4 = wx.Button(self.panel, -1, "Jeez Frank, relax")
vbox = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
hbox1.Add(Btn1, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox1.Add(Btn2, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox2.Add(Btn3, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox2.Add(Btn4, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
vbox.Add(hbox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)
vbox.Add(hbox2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)
self.panel.SetSizer(vbox)
self.panel.Layout()
self.GetAllChildren(self.panel.GetSizer())
print self.sizerItems
def GetAllChildren(self, item):
try:
for sizerItem in item.GetChildren():
self.GetAllChildren(sizerItem)
except:
try:
item.GetSizer()
self.GetAllChildren(item.GetSizer())
except:
self.sizerItems.append(item)
return
app = wx.PySimpleApp()
Tester().Show()
app.MainLoop()
This code makes a GUI with 4 buttons. I want GetAllChildren() to return a list (self.sizerItems) of all the sizerItems which are not sizers. For this example, there should be 4 elements in the list corresponding to the four buttons. GetAllChildren() should recursively run down the tree of sizers, so vbox first, then hbox1 and all its children, then hbox2 and all its children.
Currently though, I get [None,None,None,None] as the result. I realize the try...except is where it is breaking, but I don't know how else to decide whether a particular item is what I want. Any suggestions on how to fix this or alternative methods? Thanks in advance
I played around with the code a bit and changed it so that it actually returned the widget instances instead of the sizerItem instances:
import wx
from wx.lib.scrolledpanel import ScrolledPanel
class Tester(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, "Window")
self.panel = ScrolledPanel(parent=self, id=-1)
self.panel.SetupScrolling()
self.sizerItems = []
Btn1 = wx.Button(self.panel, -1, "I'm a Button!")
Btn2 = wx.Button(self.panel, -1, "Me Too!")
Btn3 = wx.Button(self.panel, -1, "Hey! Quiet up there!")
Btn4 = wx.Button(self.panel, -1, "Jeez Frank, relax")
vbox = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
hbox1.Add(Btn1, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox1.Add(Btn2, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox2.Add(Btn3, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
hbox2.Add(Btn4, flag=wx.LEFT|wx.RIGHT|wx.TOP, border=10)
vbox.Add(hbox1, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)
vbox.Add(hbox2, flag=wx.EXPAND|wx.LEFT|wx.RIGHT|wx.TOP|wx.BOTTOM, border=25)
self.panel.SetSizer(vbox)
self.panel.Layout()
self.GetAllChildren(self.panel.GetSizer())
print self.sizerItems
def GetAllChildren(self, item):
for sizerItem in item.GetChildren():
widget = sizerItem.GetWindow()
if not widget:
# then it's probably a sizer
sizer = sizerItem.GetSizer()
if isinstance(sizer, wx.Sizer):
self.GetAllChildren(sizer)
else:
self.sizerItems.append(widget)
#----------------------------------------------------------------------
if __name__ == "__main__":
app = wx.App(False)
Tester().Show()
app.MainLoop()
You can read more about this method in one of my old tutorials:
http://www.blog.pythonlibrary.org/2012/08/24/wxpython-how-to-get-children-widgets-from-a-sizer/
Which, oddly enough, is based on another StackOverflow question:
wxPython: How to get sizer from wx.StaticText?
Anyway, when I ran that code above, I got back a list of four buttons. To check and make sure they aren't the same button added 4 times, I did this:
for item in self.sizerItems:
print item.GetLabel()
You might also want to take a look at the Widget Inspection Tool which can visually show you which widgets are in which sizers.
the path you are going down leads to the darkside! turn back!
you should just do something like
def __init__(self):
...
self.widgets = {
'text_input':textBox,
'btn1':btn1,
....
}
then just access them later through
my_instance.widgets['text_input'].GetValue()
or
def validate(self):
self.widgets['text_input'].GetValue()
This program is that wx.textctrl is written "clicked" when button is clicked.
It don't run.
import wx
class Mainwindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(300, 300))
panel = wx.Panel(self, -1)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
btn = wx.Button(panel, -1, 'OK', size=(70, 30))
button = Click_btn()
btn.Bind(wx.EVT_BUTTON, button.click_btn)
hbox1.Add(btn, 0)
vbox.Add(hbox1, 0)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
self.tc = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
hbox2.Add(self.tc, 1, wx.EXPAND)
vbox.Add(hbox2, 1, wx.EXPAND)
panel.SetSizer(vbox)
self.Centre()
self.Show(True)
class Click_btn(Mainwindow):
def click_btn(self, event):
Mainwindow.tc.WriteText("clicked\n")
if __name__=="__main__":
app = wx.App()
Mainwindow(None, -1, u"sample")
app.MainLoop()
Error panel disapper immediately.
Maybe Click_btn class is wrong.
Where should I change?
You have messed up several concepts in your code:
Click_btn should probably not derive from MainWindow, but from wx.Button.
click_btn should not access MainWindow but an instance of MainWindow.
The simplest solution would be to implement the event handler as method of MainWindow and to bind that one to the button.
I would propose to read http://wiki.wxpython.org/Getting%20Started and http://www.diveintopython.net/object_oriented_framework/index.html and then give it another try.
Your Click_btn class is a subclass of your Mainwindow class, which takes 3 arguments to init, along with itself. When you create a new Click_btn, you're not passing in any arguments.
Having click_btn in its own class doesn't really make sense; move it to the Mainwindow class. The following should work:
import wx
class Mainwindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(300, 300))
panel = wx.Panel(self, -1)
vbox = wx.BoxSizer(wx.VERTICAL)
hbox1 = wx.BoxSizer(wx.HORIZONTAL)
btn = wx.Button(panel, -1, 'OK', size=(70, 30))
btn.Bind(wx.EVT_BUTTON, self.click_btn)
hbox1.Add(btn, 0)
vbox.Add(hbox1, 0)
hbox2 = wx.BoxSizer(wx.HORIZONTAL)
self.tc = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
hbox2.Add(self.tc, 1, wx.EXPAND)
vbox.Add(hbox2, 1, wx.EXPAND)
panel.SetSizer(vbox)
self.Centre()
self.Show(True)
def click_btn(self, event):
self.tc.WriteText("clicked\n")
if __name__=="__main__":
app = wx.App()
Mainwindow(None, -1, u"sample")
app.MainLoop()
I'm trying to build a small application in wxPython (absolute beginner) in which I display a login box before showing the content. I created a frame, inside the frame a panel with a flexigrid to put the login form inside but it doesn't show. If I launch the application the login form is invisible. If I resize the application the login box shows. Any idea why? Here's my code so far:
import wx
class AP_App(wx.App):
def OnInit(self):
frame = AP_MainFrame("Test application", (0, 0), (650, 350))
frame.Show()
self.SetTopWindow(frame)
loginPanel = AP_LoginPanel(frame)
self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
return True
def OnCloseWindow(self, event):
self.Destroy()
class AP_MainFrame(wx.Frame):
def __init__(self, title, pos, size):
wx.Frame.__init__(self, None, -1, title, pos, size)
self.CreateStatusBar()
class AP_LoginPanel(wx.Panel):
def __init__(self, frame):
self.panel = wx.Panel(frame)
self.frame = frame
self.frame.SetStatusText("Authentification required!")
self.showLoginBox()
def showLoginBox(self): #Create the sizer
sizer = wx.FlexGridSizer(rows = 3, cols = 2, hgap = 5, vgap = 15)
# Username
self.txt_Username = wx.TextCtrl(self.panel, 1, size = (150, -1))
lbl_Username = wx.StaticText(self.panel, -1, "Username:")
sizer.Add(lbl_Username,0, wx.LEFT|wx.TOP| wx.RIGHT, 50)
sizer.Add(self.txt_Username,0, wx.TOP| wx.RIGHT, 50)
# Password
self.txt_Password = wx.TextCtrl(self.panel, 1, size=(150, -1), style=wx.TE_PASSWORD)
lbl_Password = wx.StaticText(self.panel, -1, "Password:")
sizer.Add(lbl_Password,0, wx.LEFT|wx.RIGHT, 50)
sizer.Add(self.txt_Password,0, wx.RIGHT, 50)
# Submit button
btn_Process = wx.Button(self.panel, -1, "&Login")
self.panel.Bind(wx.EVT_BUTTON, self.OnSubmit, btn_Process)
sizer.Add(btn_Process,0, wx.LEFT, 50)
self.panel.SetSizer(sizer)
def OnSubmit(self, event):
UserText = self.txt_Username.GetValue()
PasswordText = self.txt_Password.GetValue()
if __name__ == '__main__':
app = AP_App()
app.MainLoop()
I just discovered I'm calling frame.Show() too soon. :)