wxPython showing help upon mouse focus - python

I wonder if there is any easy way to popup help (stickies style) upon focusing the mouse on a wx.Button for a second or two.
thanks

I believe you are looking for wx.ToolTip. An example:
import wx
class MyFrame(wx.Frame):
def __init__(self, title, *args, **kwargs):
super(MyFrame, self).__init__(None, title=title, *args, **kwargs)
panel = wx.Panel(self)
button = wx.Button(panel, label="Button")
tooltip = wx.ToolTip("Try to click this button")
button.SetToolTip(tooltip)
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame("Example")
self.frame.Show()
return True
MyApp(False).MainLoop()
There are some methods you can use for controlling the tip.

Related

WxPython Cut, Copy, Paste functions

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

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!

Learning wxPython, basic thing

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

wxPython CollapsiblePane strange clipping issue

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.

How can I make a wxPython app constantly update and execute code?

Given the following simple program:
import wx
class TestDraw(wx.Panel):
def __init__(self,parent=None,id=-1):
wx.Panel.__init__(self,parent,id,style=wx.TAB_TRAVERSAL)
self.SetBackgroundColour("#FFFFFF")
self.Bind(wx.EVT_PAINT,self.onPaint)
self.SetDoubleBuffered(True)
self.circleX=320
self.circleY=240
def onPaint(self, event):
event.Skip()
dc=wx.PaintDC(self)
dc.BeginDrawing()
dc.DrawCircle(self.circleX,self.circleY,100)
dc.EndDrawing()
class TestFrame(wx.Frame):
def __init__(self, parent, title):
wx.Frame.__init__(self, parent, title=title, size=(640,480))
self.mainPanel=TestDraw(self,-1)
self.Show(True)
app = wx.App(False)
frame = TestFrame(None,"Test App")
app.MainLoop()
How can I change it so that I can execute logic and repaint the panel at a constant rate? I'd like the circle to bounce around the screen, but I just can't figure out the place I would change its x and y variables.
Your can use a wxTimer to periodically call an onTimer(self) method.

Categories

Resources