How would I add a link to my menu item in wxpython? - python

How would I add a link to my menu item in wxpython? What I want is when the user clicks the menu item it will go to my website. Is this even possible?
Thanks in advance!! Oh and I am fairly new to programming and to python so if you could dumb it down alittle that would be appreciated!! Thanks
THIS IS MY CODE:
import wx
class MainWindow(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self,parent,id,'Python Test App',size=(600,400))
panel=wx.Panel(self)
wx.Frame.CenterOnScreen(self)
self.SetBackgroundColour(wx.BLACK)
##MENU AND STATUS BAR
status=self.CreateStatusBar()
menubar=wx.MenuBar()
file_menu=wx.Menu()
help_menu=wx.Menu()
ID_FILE_NEW = 1
ID_FILE_EXIT = 2
ID_HELP_ABOUT = 3
ID_HELP_WEB = 4
file_menu.Append(ID_FILE_NEW,"New Window","This will open a new window")
file_menu.Append(ID_FILE_EXIT,"Exit","This will exit the program")
help_menu.Append(ID_HELP_ABOUT,"About","This will tell you about %name%")
help_menu.Append(ID_HELP_WEB,"Visit Website","This will take you to worm-media.host56.com")
menubar.Append(file_menu,"File")
menubar.Append(help_menu,"Help")
self.SetMenuBar(menubar)
self.Bind(wx.EVT_MENU, self.newWin, None, 1)
self.Bind(wx.EVT_MENU, self.close, None, 2)
self.Bind(wx.EVT_MENU, self.about, None, 3)
##self.Bind(wx.EVT_MENU, self.web, None, 4)
heading = wx.StaticText(panel, -1, 'Welcome to My App', (144,10))
heading.SetForegroundColour(wx.RED)
font1 = wx.Font(20, wx.DEFAULT, wx.NORMAL, wx.BOLD)
heading.SetFont(font1)
def newWin(self, event):
self.new = NewWindow(parent=None, id=-1)
self.new.Show()
def close(self, event):
box=wx.MessageDialog(None, 'Are you sure you want to exit?', 'Exit program?', wx.YES_NO)
answer=box.ShowModal()
if answer==wx.ID_YES:
self.Destroy()
def about(self, event):
self.new = AboutWindow(parent=None, id=-1)
self.new.Show()
##def web(self, event):
class NewWindow(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self, parent, id, 'New Window', size=(400,300))
wx.Frame.CenterOnScreen(self)
##panel2=wx.Panel(self)
name_text = wx.StaticText(self, -1, 'What is your name?')
name = wx.TextCtrl(self, -1, '', (100,0))
font2 = wx.Font(8, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
name_text.SetFont(font2)
class AboutWindow(wx.Frame):
def __init__(self,parent,id):
wx.Frame.__init__(self, parent, id, 'About', size=(300,190))
wx.Frame.CenterOnScreen(self)
self.SetBackgroundColour(wx.WHITE)
about_bg = 'about_bg.jpg'
bmp1 = wx.Image(about_bg, wx.BITMAP_TYPE_ANY).ConvertToBitmap()
self.bitmap1 = wx.StaticBitmap(self, -1, bmp1, (0,0))
##ABOUT_TEXT
by_text = wx.StaticText(self, -1, 'Made By: Worm', (50,70))
version_text = wx.StaticText(self, -1, 'Version: 1.0', (50,90))
website_text = wx.StaticText(self, -1, 'Website: worm-media.host56.com', (50,110))
##ABOUT_FONTS
by_font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
version_font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
website_font = wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.NORMAL)
by_text.SetFont(by_font)
version_text.SetFont(version_font)
website_text.SetFont(website_font)
##ABOUT_COLORS
by_text.SetBackgroundColour(wx.WHITE)
version_text.SetBackgroundColour(wx.WHITE)
website_text.SetBackgroundColour(wx.WHITE)
##RUN##
if __name__=='__main__':
app=wx.PySimpleApp()
frame=MainWindow(parent=None,id=-1)
frame.Show()
app.MainLoop()
This is my code so far. I really haven't tried anything with this because I'm not even sure where to start. I tried looking how to do this online and came up empty. I guess all I'm asking is how to make a link in python to my website from the menu bar under about/Visit Website.

The functionality you want is actually built into Python. Check the webbrowser API. Specifically, look at the webbrowser.open() function.

In the event handler for the specific menu, you can use Python's own webbrowser,open() method. Or you can use subprocess to open a specific browser (assuming there's more than one installed). The latter would give you more control. There's also os.startfile(), but I'm not sure that would work in this case.

Related

Make TextCtrl Scale with Window

I've just gotten into wxpython for Python 3.6 and I've hit a roadblock. I just can't work out how to make elements/widgets scale with the screen! I know you have to use sizers but that's about it, I'm still fairly new to programming so just reading the documentation didn't help. If someone could just sample some code that works I'd be very thankful as I could then read through it and work out what I was doing wrong. The code that draws out the GUI I want to scale with window size is below, the key idea is that the TextCtrl scales, other elements don't really need scaling.
def createGUI(self):
panel = wx.Panel(self)
menuBar = wx.MenuBar()
menuButton = wx.Menu()
newItem = wx.MenuItem(menuButton, wx.ID_NEW, 'New Note\tCtrl+N')
delItem = wx.MenuItem(menuButton, wx.ID_DELETE, 'Delete Note\tCtrl+Backspace')
saveItem = wx.MenuItem(menuButton, wx.ID_SAVE, 'Save\tCtrl+S')
exitItem = wx.MenuItem(menuButton, wx.ID_EXIT, 'Quit\tCtrl+Q')
menuButton.Append(newItem)
menuButton.Append(saveItem)
menuButton.Append(delItem)
menuButton.Append(exitItem)
menuBar.Append(menuButton, 'Menu')
self.SetMenuBar(menuBar)
self.Bind(wx.EVT_MENU, self.new, newItem)
self.Bind(wx.EVT_MENU, self.delete, delItem)
self.Bind(wx.EVT_MENU, self.save, saveItem)
self.Bind(wx.EVT_MENU, self.onExit, exitItem)
self.noteText = wx.TextCtrl(panel)
self.noteText.AppendText(self.notecontent)
self.Bind(wx.EVT_CLOSE, self.onExit)
self.SetTitle(f'Welcome {self.username}! You are working on {self.notepath}')
self.Centre()
self.Show(True)
To begin with it's best to equate sizers to something familiar and I usually think of storage boxes or a chest of drawers.
When we define widgets, they are all dumped into a container, the parent object, often the ubiquitous self or self.panel.
If we do not assign a size and pos to each item, it's just a jumbled mess, a pile of widgets.
The sizer, there are many types, are the virtual drawers in our chest of drawers, that herds this pile of widgets into order.
The widgets are assigned to the appropriate sizer, note sizers can go into other sizers, and eventually when everything has been assigned a place or drawer in our chest of drawers, the sizers do their magic, arranging and sizing all of widgets into a coherent screen for display or arranging the drawers contents and relative positions in the chest of drawers.
Below, I've used the simplest sizer a boxsizer.
One will arrange things vertically and the other horizontally.
The horizontal sizer is for the buttons and the vertical sizer, will be the main sizer, into which I place not only the TectCtrl but also the buttons, prearranged in their horizontal sizer.
For a better and more comprehensive description of sizers and their controls see: https://docs.wxpython.org/sizers_overview.html and for details on the actual sizers available see the detailed documenation on each.
A loose approximation of your code:
#!/usr/bin/python
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title,
size=(450, 350))
self.panel = wx.Panel(self, -1)
self.main_sizer = wx.BoxSizer(wx.VERTICAL)
self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
self.noteText = wx.TextCtrl(self.panel, -1, style=wx.TE_MULTILINE)
self.Button_close = wx.Button(self.panel, -1, label="Quit")
self.Button_1 = wx.Button(self.panel, -1, label="Btn1")
self.Button_2 = wx.Button(self.panel, -1, label="Btn2")
self.Bind(wx.EVT_CLOSE, self.onExit)
self.Button_close.Bind(wx.EVT_BUTTON, self.onExit)
self.Button_1.Bind(wx.EVT_BUTTON, self.onButton)
self.Button_2.Bind(wx.EVT_BUTTON, self.onButton)
# Place buttons within their own horizontal sizer
self.button_sizer.Add(self.Button_close,proportion=0, flag=wx.ALL, border=10)
self.button_sizer.Add(self.Button_1,proportion=0, flag=wx.ALL, border=10)
self.button_sizer.Add(self.Button_2,proportion=0, flag=wx.ALL, border=10)
# Add textctrl and the button sizer to the main sizer (vertical)
self.main_sizer.Add(self.noteText,proportion=1, flag=wx.EXPAND|wx.ALL, border=10)
self.main_sizer.Add(self.button_sizer, 0, 0, 0)
self.panel.SetSizer(self.main_sizer)
self.Show()
def onExit(self, event):
self.Destroy()
def onButton(self, event):
print("A button was pressed")
if __name__ == '__main__':
app = wx.App()
Example(None, title="Example")
app.MainLoop()
Edit:
Here's the same code without using sizers, although they are recommended.
#!/usr/bin/python
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
super(Example, self).__init__(parent, title=title,
size=(450, 350))
self.panel = wx.Panel(self, -1)
self.noteText = wx.TextCtrl(self.panel, -1, pos=(10,10), size=(400,280), style=wx.TE_MULTILINE)
self.Button_close = wx.Button(self.panel, -1, label="Quit", pos=(10,290), size=(50,30))
self.Button_1 = wx.Button(self.panel, -1, label="Btn1", pos=(70,290), size=(50,30))
self.Button_2 = wx.Button(self.panel, -1, label="Btn2", pos=(130,290), size=(50,30))
self.Bind(wx.EVT_CLOSE, self.onExit)
self.Button_close.Bind(wx.EVT_BUTTON, self.onExit)
self.Button_1.Bind(wx.EVT_BUTTON, self.onButton)
self.Button_2.Bind(wx.EVT_BUTTON, self.onButton)
self.Show()
def onExit(self, event):
self.Destroy()
def onButton(self, event):
print("A button was pressed")
if __name__ == '__main__':
app = wx.App()
Example(None, title="Example")
app.MainLoop()

Bind “Enter” key to WXPython "AquaButton" Button with Focus

I am new to this site and fairly new to Python. I am working on a program using wxPython for the GUI. This is being developed and will be used on Windows OS machines. The GUI uses a number of buttons that trigger different processes in my script. I decided to try using the AGW AquaButtons for visual interest. I am finding that an "AquaButton" with focus will not respond to pressing the "Enter" key while the standard "wx.Button" does. Below are examples (mostly borrowed from similar questions, thanks "Rolf of Saxony" and "Mike Driscoll") of the working and non-working code.
Is there a way to get an "AquaButton" (with Focus) have it's event triggered by the "Enter" key?
This works:
import wx
class Example(wx.Frame):
def __init__(self, parent, title):
frame = wx.Frame.__init__(self, parent, title=title, )
self.panel = wx.Panel(self, -1, size=(200,100))
self.btn1 = wx.Button(self.panel, label='Button 1', id=1)
self.btn1.SetForegroundColour("black")
self.btn2 = wx.Button(self.panel, label='Button 2', id=2)
self.btn2.SetForegroundColour("black")
self.sizer = wx.GridBagSizer(0, 0)
self.sizer.Add(self.btn1, pos=(0, 0), flag=wx.ALIGN_CENTER)
self.sizer.Add(self.btn2, pos=(1, 0), flag=wx.ALIGN_CENTER)
self.text_box = wx.StaticText(self.panel, style = wx.NO_BORDER)
self.text_box.SetFont(wx.Font(14, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, ""))
self.text_box.SetForegroundColour((40,115,180))
self.sizer.Add(self.text_box, pos=(2,0), flag=wx.ALIGN_CENTER)
self.Bind(wx.EVT_BUTTON, self.button_press)
self.panel.SetSizer(self.sizer)
self.Show()
def button_press(self, event):
Id = event.GetId()
print ('Click Button',str(Id))
retVal = F"Click Button {Id}"
self.text_box.SetLabel(str(retVal))
class AppMenu(wx.App):
def OnInit(self):
'Create the main window and insert the custom frame'
frame = Example(None, 'Example')
frame.Show(True)
return True
app = AppMenu()
app.MainLoop()
This doesn't:
import wx
import wx.lib.agw.aquabutton as AB
class Example(wx.Frame):
def __init__(self, parent, title):
frame = wx.Frame.__init__(self, parent, title=title, )
self.panel = wx.Panel(self, -1, size=(200,100))
self.btn1 = AB.AquaButton(self.panel, label='Button 1', id=1)
self.btn1.SetForegroundColour("black")
self.btn2 = AB.AquaButton(self.panel, label='Button 2', id=2)
self.btn2.SetForegroundColour("black")
self.sizer = wx.GridBagSizer(0, 0)
self.sizer.Add(self.btn1, pos=(0, 0), flag=wx.ALIGN_CENTER)
self.sizer.Add(self.btn2, pos=(1, 0), flag=wx.ALIGN_CENTER)
self.text_box = wx.StaticText(self.panel, style = wx.NO_BORDER)
self.text_box.SetFont(wx.Font(14, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, 0, ""))
self.text_box.SetForegroundColour((40,115,180))
self.sizer.Add(self.text_box, pos=(2,0), flag=wx.ALIGN_CENTER)
self.Bind(wx.EVT_BUTTON, self.button_press)
self.panel.SetSizer(self.sizer)
self.Show()
def button_press(self, event):
Id = event.GetId()
print ('Click Button',str(Id))
retVal = F"Click Button {Id}"
self.text_box.SetLabel(str(retVal))
class AppMenu(wx.App):
def OnInit(self):
'Create the main window and insert the custom frame'
frame = Example(None, 'Example')
frame.Show(True)
return True
app = AppMenu()
app.MainLoop()
Bizarrely, the AquaButton is pressed using the Spacebar and not the Enter key.
Navigating appears to be via Arrow keys and/or Tab and Shift Tab.
If in doubt the source code is in:
your_python_location/dist-packages/wx/lib/agw/aquabutton.py
I hope that clears that up for you, if not for your users. :)

wxPython, Getting input from TextCtrl box to send to Notepad

I am trying to create a simple invoice program for a school project. I have the basic layout of my program.
The large text boxes on the left are for the invoice, and the ones on the right are for the price of that input.
I want the text boxes to return the input into them, and assign it to say JobOne. The next step is that I need these values to be send to a file in Notepad when the 'Send To Invoice' button is clicked.
I am really stuck here, I've tried so many different combinations of things, and I'm forever getting "TextCtrl" object is not callable.
Any help would be greatly appreciated.
I've taken out my messy attempts to get the problem working and stripped it down to its barebones.
import wx
class windowClass(wx.Frame):
def __init__(self, *args, **kwargs):
super(windowClass, self).__init__(*args, **kwargs)
self.basicGUI()
def basicGUI(self):
panel = wx.Panel(self)
self.SetSizeWH(1200, 800)
menuBar = wx.MenuBar()
fileButton = wx.Menu()
exitItem = fileButton.Append(wx.ID_EXIT, 'Exit', 'status msg...')
menuBar.Append(fileButton, 'File')
self.SetMenuBar(menuBar)
self.Bind(wx.EVT_MENU, self.Quit, exitItem)
yesNoBox = wx.MessageDialog(None, 'Do you wish to create a new invoice?',
'Create New Invoice?', wx.YES_NO)
yesNoAnswer = yesNoBox.ShowModal()
yesNoBox.Destroy()
nameBox = wx.TextEntryDialog(None, 'What is the name of the customer?', 'Customer Name'
, 'Customer Name')
if nameBox.ShowModal() ==wx.ID_OK:
CustomerName = nameBox.GetValue()
wx.TextCtrl(panel, pos=(10, 10), size=(500,100))
wx.TextCtrl(panel, pos=(550, 10), size=(60,20))
wx.TextCtrl(panel, pos=(10, 200), size=(500,100))
wx.TextCtrl(panel, pos=(550, 200), size=(60,20))
wx.TextCtrl(panel, pos=(10, 400), size=(500,100))
wx.TextCtrl(panel, pos=(550, 400), size=(60,20))
self.SetTitle('Invoice For ' +CustomerName)
SendToNotepadButton = wx.Button(panel, label='Convert to invoice',pos=(650, 600), size=(120, 80))
def SendToNotepad(e):
f = open("Notepad.exe", 'w')
f.write(())
call(["Notepad.exe", "CustomerInvoice"])
self.Bind(wx.EVT_BUTTON, SendToNotepad)
self.Show(True)
def Quit(self, e):
self.Close()
def main():
app = wx.App()
windowClass(None)
app.MainLoop()
main()
If you manage to help me, I thank you!
This is actually fairly easy. I skipped the MessageDialog stuff and just put together a proof of concept. This worked for me on my Windows 7 box with Python 2.7 and wxPython 3.0.2:
import subprocess
import wx
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
self.txt = wx.TextCtrl(self)
notepad_btn = wx.Button(self, label="Send to Invoice")
notepad_btn.Bind(wx.EVT_BUTTON, self.onSendInvoice)
my_sizer = wx.BoxSizer(wx.VERTICAL)
my_sizer.Add(self.txt, 0, wx.EXPAND|wx.ALL, 5)
my_sizer.Add(notepad_btn, 0, wx.CENTER|wx.ALL, 5)
self.SetSizer(my_sizer)
#----------------------------------------------------------------------
def onSendInvoice(self, event):
""""""
txt = self.txt.GetValue()
print txt
# write to file
with open("invoice.txt", 'w') as fobj:
fobj.write(txt)
# open Notepad
subprocess.Popen(['notepad.exe', 'invoice.txt'])
########################################################################
class MainWindow(wx.Frame):
""""""
#----------------------------------------------------------------------
def __init__(self):
"""Constructor"""
wx.Frame.__init__(self, None, title="Jobs")
panel = MyPanel(self)
self.Show()
if __name__ == '__main__':
app = wx.App(False)
frame = MainWindow()
app.MainLoop()
Hopefully this code will help you see how to put it all together.

wxpython cut copy and paste throughout the application

I'm developing a small application with multiple TextCtrl and ComboBox widgets. I want that when I press the key Ctrl-C Ctrl-V and Ctrl-X I get the usual behaviour of copying, pasting and cutting in the appropriate entry.
What I obtain right now is that, while I can right-click and have the text copd/past/cutd, I can't through the keybindings or the menu entries. How can I obtain this in a simple way?
Menu keybindings work by default with Alt-first_menu_letter -> submenu_first_letter.
The menu event of the selected item should bind the corresponding event handler:
self.Bind(wx.EVT_MENU, self.on_copy, self.copy)
for a copy method, you first select the text you want to copy with the mouse. Then you can get the widget that is focused (the specific textcontrol with the selected string to be copied) with:
widget = self.FindFocus()
in this way now you can get the selected string from that widget:
self.copied = widget.GetStringSelection()
And the same has to be done for pasting the copied text in the textctrl you situate the cursor.
Here you have a working example:
import wx
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
kwds["style"] = wx.DEFAULT_FRAME_STYLE
wx.Frame.__init__(self, *args, **kwds)
self.tctrl_1 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE)
self.tctrl_2 = wx.TextCtrl(self, -1, "", style=wx.TE_MULTILINE)
self.menubar = wx.MenuBar()
self.test = wx.Menu()
self.copy = wx.MenuItem(self.test, wx.NewId(), "copy", "is_going to copy", wx.ITEM_NORMAL)
self.test.AppendItem(self.copy)
self.paste = wx.MenuItem(self.test, wx.NewId(), "paste", "will paste", wx.ITEM_NORMAL)
self.test.AppendItem(self.paste)
self.menubar.Append(self.test, "Test")
self.SetMenuBar(self.menubar)
self.__set_properties()
self.__do_layout()
self.Bind(wx.EVT_MENU, self.on_copy, self.copy)
self.Bind(wx.EVT_MENU, self.on_paste, self.paste)
def __set_properties(self):
self.SetTitle("frame_1")
def __do_layout(self):
sizer_1 = wx.BoxSizer(wx.VERTICAL)
sizer_2 = wx.BoxSizer(wx.HORIZONTAL)
sizer_2.Add(self.tctrl_1, 1, wx.EXPAND, 0)
sizer_2.Add(self.tctrl_2, 1, wx.EXPAND, 0)
sizer_1.Add(sizer_2, 1, wx.EXPAND, 0)
self.SetSizer(sizer_1)
sizer_1.Fit(self)
self.Layout()
def on_copy(self, event):
widget = self.FindFocus()
self.copied = widget.GetStringSelection()
def on_paste(self, event):
widget = self.FindFocus()
widget.WriteText(self.copied)
if __name__ == "__main__":
app = wx.PySimpleApp(0)
frame = MyFrame(None, -1, "")
frame.Show()
app.MainLoop()

How to set the size of a wx.aui.AuiManager Pane that is centered?

I have three panes with the InfoPane center option.
I want to know how to set their size.
Using 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)
text3 = wx.TextCtrl(self, -1, 'Main content window',
wx.DefaultPosition, wx.Size(200,150),
wx.NO_BORDER | wx.TE_MULTILINE)
# add the panes to the manager
self._mgr.AddPane(text1, wx.CENTER)
self._mgr.AddPane(text2, wx.CENTER)
self._mgr.AddPane(text3, wx.CENTER)
# tell the manager to 'commit' all the changes just made
self._mgr.Update()
self.Bind(wx.EVT_CLOSE, self.OnClose)
def OnClose(self, event):
# deinitialize the frame manager
self._mgr.UnInit()
# delete the frame
self.Destroy()
app = wx.App()
frame = MyFrame(None)
frame.Show()
app.MainLoop()
I want to know what is called when we change the size of the panes.
If you tell me that, I can do the rest by myself :)
I've discovered what I want.
It was the wx.aui.AuiPaneInfo.dock_proportion property :)

Categories