I am making a small application and I have trouble defining efficient "Edit" menu functions.
I have tried this:
from pyautogui import hotkey
.
.
.
def OnCopy ( self, event ):
hotkey ( 'ctrl, 'c' )
However, the above doesn't always work and even breaks sometimes. Is there a better method?
wxPython has its own Clipboard object. Its implementation depends on the use of a wxDataObject because, of course, you can copy and paste many types of data onto the clipboard
import wx
class MainFrame(wx.Frame):
"""Create MainFrame class."""
def __init__(self, *args, **kwargs):
super().__init__(None, *args, **kwargs)
self.size = (400, 1000)
self.panel = MainPanel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.panel)
self.SetSizer(sizer)
self.Center()
self.Show()
def on_copy(self, event):
if wx.TheClipboard.Open():
# Put some text onto the clipboard
text = self.panel.txt_input.GetValue()
data_object = wx.TextDataObject(text)
wx.TheClipboard.SetData(data_object)
# Now retrieve it from the clipboard and print the value
text_data = wx.TextDataObject()
success = wx.TheClipboard.GetData(text_data)
wx.TheClipboard.Close()
if success:
print(f'This data is on the clipboard: {text_data.GetText()}')
class MainPanel(wx.Panel):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.parent = parent
self.txt_input = wx.TextCtrl(self)
cmd_copy = wx.Button(self, wx.ID_COPY)
cmd_copy.Bind(wx.EVT_BUTTON, parent.on_copy)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.txt_input)
sizer.Add(cmd_copy)
self.SetSizer(sizer)
if __name__ == '__main__':
wx_app = wx.App()
MainFrame()
wx_app.MainLoop()
Related
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!
i have two py files that each have its own frame made using wxPython, MainWindow and RecWindow. MainWindow has the RecWindow python file included using the keyword "recovery".
MainWindow code:
class MainWindow(wx.Frame):
def __init__(self,parent,id,title):
wx.Frame.__init__(self, parent, wx.ID_ANY,title,pos=(500,200), size = (650,500), style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
self.Bind(wx.EVT_CLOSE,self.OnExit)
self.SetIcon(wx.Icon('etc\icons\download.ico', wx.BITMAP_TYPE_ICO))
panel = wx.Panel(self)
RecWindow code:
class RecWindow(wx.Frame):
def __init__(self,parent,id,title):
wx.Frame.__init__(self, parent, wx.ID_ANY,title,pos=(400,200), size = (700,600), style = wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
self.SetIcon(wx.Icon('etc\icons\download.ico', wx.BITMAP_TYPE_ICO))
self.count = 0
when i click on a button in MainWindow , it will hide the MainWindow create an instance of RecWindow, shown below;
def OpenRec(self,event):#this will be used to open the next frame
OR = recovery(None,-1,"RAVE")
OR.Show(True)
MainWindow.Hide()
now, what i am unsure of is how i can return to the MainWindow once i close the RecWindow. RecWindow has a cancel and finish button which both map to a self.close() function. How would i then get MainWindow to show itself again?
Use pubsub to send a message to the main window telling it to Show itself again. I actually have an example of how to do that here:
http://www.blog.pythonlibrary.org/2010/06/27/wxpython-and-pubsub-a-simple-tutorial/
Note that this tutorial is using slightly older API that was available in wxPython 2.8. If you're using wxPython 2.9, then you'll have to use the slightly different API that I detail in this article:
http://www.blog.pythonlibrary.org/2013/09/05/wxpython-2-9-and-the-newer-pubsub-api-a-simple-tutorial/
When you create an instance of RecWindow keep a reference to it on main_window and bind to its close event.
In the main_window's close handler check if the window closed was the RecWindow.
If it was, clear the reference to it and show the main_window.
Elif the closed window was main_window carry out any required code.
Finally call event.Skip() so the windows get destroyed.
import wx
class MainWindow(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title, (500, 200), (650, 500),
wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
panel = wx.Panel(self)
button = wx.Button(panel, wx.ID_OPEN)
panel.sizer = wx.BoxSizer(wx.VERTICAL)
panel.sizer.Add(button, 0, wx.ALL, 7)
panel.SetSizer(panel.sizer)
button.Bind(wx.EVT_BUTTON, self.on_button)
self.Bind(wx.EVT_CLOSE, self.on_close)
self.rec_window = None
def on_button(self, event):
rec_window = RecWindow(self, 'Rec window')
rec_window.Show()
self.Hide()
rec_window.Bind(wx.EVT_CLOSE, self.on_close)
self.rec_window = rec_window
def on_close(self, event):
closed_window = event.EventObject
if closed_window == self.rec_window:
self.rec_window = None
self.Show()
elif closed_window == self:
print 'Carry out your code for when Main window closes'
event.Skip()
class RecWindow(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, -1, title, (400, 200), (700, 600),
wx.DEFAULT_FRAME_STYLE | wx.NO_FULL_REPAINT_ON_RESIZE)
app = wx.App(False)
main_window = MainWindow(None, 'Main window')
main_window.Show()
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()
This is a follow up from allocating more size in sizer to wx.CollapsiblePane when expanded.
EDIT: The answer to that question solved my original problem, which was that nothing moved when I expanded or collapsed a pane, but now I've encountered another bug. While things do move properly, the buttons seem to smear out over each other as shown in the image below. Mousing over a button seems to force it to redraw properly over the rest of the mess, but it leaves a bunch of random button pieces drawn behind and around it.
I've done my absolute best to replicate this bug in a sample app, but I can't. I'm just looking for leads here. Does anyone have any idea what might cause the kind of issue shown below? It only happens after expanding and collapsing some of the upper panes.
For what it's worth, code below is for a sample app that looks very similar, but for some reason doesn't cause the same problems. EDIT Also for what it's worth, here's a link to the full source code for the GUI of my project which generated the screenshot below. http://code.google.com/p/dicom-sr-qi/source/browse/gui/main.py?r=8a876f7b4a034df9747a2c1f2791258f671e44b1
import wx
class SampleSubPanel(wx.Panel):
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
sizer = wx.BoxSizer(wx.HORIZONTAL)
sizer.Add(wx.StaticText(self, 1, "A label"))
sizer.Add(wx.SpinCtrl(self))
self.SetSizer(sizer)
class SampleCollapsiblePane(wx.CollapsiblePane):
def __init__(self, *args, **kwargs):
wx.CollapsiblePane.__init__(self,*args,**kwargs)
sizer = wx.BoxSizer(wx.VERTICAL)
for x in range(2):
sizer.Add(wx.CheckBox(self.GetPane(), label = str(x)))
sizer.Add(SampleSubPanel(self.GetPane()))
self.GetPane().SetSizer(sizer)
self.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.on_change)
def on_change(self, event):
self.GetParent().Layout()
class SampleSubPanel2(wx.Panel):
def __init__(self, *args, **kwargs):
wx.Panel.__init__(self, *args, **kwargs)
sizer = wx.BoxSizer(wx.VERTICAL)
for x in range(2):
sizer.Add(SampleCollapsiblePane(self, label = str(x)), 0)
self.SetSizer(sizer)
class Main_Frame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.main_panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(wx.Panel(self.main_panel, style=wx.RAISED_BORDER),1, wx.EXPAND)
sizer.Add(SampleSubPanel2(self.main_panel, style = wx.RAISED_BORDER),2, wx.EXPAND )
sizer.Add(wx.Button(self.main_panel,label= "a button"),0,wx.ALIGN_CENTER)
self.main_panel.SetSizer(sizer)
class SampleApp(wx.App):
def OnInit(self):
frame = Main_Frame(None, title = "Sample App")
frame.Show(True)
frame.Centre()
return True
def main():
app = SampleApp(0)
app.MainLoop()
if __name__ == "__main__":
main()
If I am getting you right, you want the code here - allocating more size in sizer to wx.CollapsiblePane when expanded to work properly. The reason it did not work was you forgot to bind the wx.EVT_COLLAPSIBLEPANE_CHANGED. Here is a code which worked for me -
import wx
class SampleCollapsiblePane(wx.CollapsiblePane):
def __init__(self, *args, **kwargs):
wx.CollapsiblePane.__init__(self,*args,**kwargs)
sizer = wx.BoxSizer(wx.VERTICAL)
for x in range(5):
sizer.Add(wx.Button(self.GetPane(), label = str(x)))
self.GetPane().SetSizer(sizer)
self.Bind(wx.EVT_COLLAPSIBLEPANE_CHANGED, self.on_change)
def on_change(self, event):
self.GetParent().Layout()
class Main_Frame(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
self.main_panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL)
for x in range(5):
sizer.Add(SampleCollapsiblePane(self.main_panel, label = str(x)), 0)
self.main_panel.SetSizer(sizer)
class SampleApp(wx.App):
def OnInit(self):
frame = Main_Frame(None, title = "Sample App")
frame.Show(True)
frame.Centre()
return True
def main():
app = SampleApp(0)
app.MainLoop()
if __name__ == "__main__":
main()
EDIT: Looks like it may be a bug in wxPython running on windows. Below is screen shot of the the exact same code that has problems on Windows running on Ubuntu with no problems.
What event is used when I close a tab in an auinotebook? I tested with
EVT_AUINOTEBOOK_PAGE_CLOSE(D). It didn't work.
I would also like to fire a right click on the tab itself event.
Where can I find all the events that can be used with the aui manager/notebook? Might just be my poor searching skills, but I can't find any lists over the different events that exist, not for mouse/window events either. It would be really handy to have a complete list.
#!/usr/bin/python
#12_aui_notebook1.py
import wx
import wx.lib.inspection
class MyFrame(wx.Frame):
def __init__(self, *args, **kwds):
wx.Frame.__init__(self, *args, **kwds)
self.nb = wx.aui.AuiNotebook(self)
self.new_panel('Page 1')
self.new_panel('Page 2')
self.new_panel('Page 3')
self.nb.Bind(wx.EVT_AUINOTEBOOK_PAGE_CLOSED, self.close)
def new_panel(self, nm):
pnl = wx.Panel(self)
pnl.identifierTag = nm
self.nb.AddPage(pnl, nm)
self.sizer = wx.BoxSizer()
self.sizer.Add(self.nb, 1, wx.EXPAND)
self.SetSizer(self.sizer)
def close(self, event):
print 'closed'
class MyApp(wx.App):
def OnInit(self):
frame = MyFrame(None, -1, '12_aui_notebook1.py')
frame.Show()
self.SetTopWindow(frame)
return 1
if __name__ == "__main__":
app = MyApp(0)
# wx.lib.inspection.InspectionTool().Show()
app.MainLoop()
Oerjan Pettersen
This is the bind command you want:
self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSED, self.close, self.nb)
To detect a right click on the tab (e.g. to show a custom context menu):
self.Bind(wx.aui.EVT_AUINOTEBOOK_TAB_RIGHT_DOWN, self.right, self.nb)
Here's a list of the aui notebook events:
EVT_AUINOTEBOOK_PAGE_CLOSE
EVT_AUINOTEBOOK_PAGE_CLOSED
EVT_AUINOTEBOOK_PAGE_CHANGED
EVT_AUINOTEBOOK_PAGE_CHANGING
EVT_AUINOTEBOOK_BUTTON
EVT_AUINOTEBOOK_BEGIN_DRAG
EVT_AUINOTEBOOK_END_DRAG
EVT_AUINOTEBOOK_DRAG_MOTION
EVT_AUINOTEBOOK_ALLOW_DND
EVT_AUINOTEBOOK_DRAG_DONE
EVT_AUINOTEBOOK_BG_DCLICK
EVT_AUINOTEBOOK_TAB_MIDDLE_DOWN
EVT_AUINOTEBOOK_TAB_MIDDLE_UP
EVT_AUINOTEBOOK_TAB_RIGHT_DOWN
EVT_AUINOTEBOOK_TAB_RIGHT_UP
From: {python folder}/Lib/site-packages/{wxpython folder}/wx/aui.py