My wx.Frame derived class is managed by AuiManager. I have several panes in this frame (all are derived from wx.Panel and all have wx.TAB_TRAVERSAL flag set). Pressing TAB key on the keyboard moves focus inside every pane correctly. The problem is, I don't know how to (or even if it is possible) move focus to the next pane. Any ideas about this?
P.S. I've tried googling and reading through wxPython docs, but couldn't find any clue.
I try to be as helpful as I can, given the little information you provided. To shift the focus to another Panel use that Panel's SetFocus() function. (See function description in the link)
Your question also seems to imply that you are interested in the key bindings of focus events. To manage the key bindings to focus events in wxpython, please checkout wx.NavigationKeyEvent. This will allow you to get and set the directions and events resulting from your navigation key inputs.
Last, have you tried pressing the [page down] key for switching panes?
Related
Morning, I would like to call a function in my GUI in the event that the content of a TextCtrl is changed. Only after the user leaves the TextCtrl object though, not during editing.
Please can you help me find the right event handler to use, I'm very new to wxpython and I can't even find a list of allowable events.
Many thanks
You can bind the TextCtrl to wx.EVT_TEXT to capture changes to the value and wx.EVT_KILL_FOCUS to trigger an even when the focus changes. Alternatively you could bind it to wx.EVT_SET_FOCUS and save the current TextCtrl value and also bind to it wx.EVT_KILL_FOCUS to and compare the new value to see if it's changed.
------- EDIT -------
WxFormBuilder is fantastic tool for quickly creating basic UIs. It will also show you every event that you can bind to a widget by clicking on the 'events'` tab.
The Problem:
It seems like one event is disabling another event. Before calling event B, event A works just fine. After event B fires, event A no longer works. Both events are custom ones that people made for their wxPython libraries (FloatCanvas and ColourSelect). I'd like to trace the generated events to make sure that, after event B, event A is still being fired (but perhaps not triggering the handler code?)
The Details:
I have a wxPython app where I create a wx.Panel object with two child items - a plot and a legend. This top level panel handles the majority of the events.
The plot is a wx.Panel object with a single wx.lib.FloatCanvas.FloatCanvas canvas in it.
The legend is a wx.Panel with multiple wx.StaticText and wx.lib.colourselect.ColourSelect objects in it (I'm plotting discrete data points).
On the plot, I bind FloatCanvas.EVT_MOUSEWHEEL to my zoom in/out function. On the legend, I bind the wx.lib.colourselect.EVT_COLOURSELECT event to my update_colors function which then sends the event to the parent panel via wx.PostEvent(event).
The parent panel then receives EVT_COLOURSELECT from the child and executes code that changes the colors of my plots.
Source Code:
I haven't had time to write a small sample that demo's the problem, but you can see the problem by running the source code:
https://github.com/dougthor42/wafer_map
Run the wm_app.py file and then go through the following test steps.
Testing Steps:
Scroll/zoom in and out - works just fine
Change a plot color (fires EVT_COLOURSELECT). If you're testing with the source code you do this by clicking on a legend color box and choosing a new color.
Attempt to zoom in and out again. Doesn't work!
Verify that all other events (key down, click-and-drag, mouse move) all work.
Things I've Tried:
Obviously these didn't work or else I wouldn't be here :-P
Unbinding the mousewheel event and rebinding it when the top level panel receives the event from the child.
Completely disabling the handlers for EVT_COLOURSELECT in both the parent panel and the legend.
I thought that perhaps there was something going on in my handlers. Turns out, just
triggering EVT_COLOURSELECT causes the EVT_MOUSEWHEEL to stop working.
Changing FloatCanvas.EVT_MOUSEWHEEL to some other event, for example FloatCanvas.EVT_RIGHT_DOWN
This does actually work! I loose the 'speed' info from the mouse wheel, but right-clicking
before and after step 2 both work.
Seems to indicate that it's an issue with the mouse scroll event specifically.
Has anyone had a problem where events interfere with each other?
It turns out that there wasn't any interference with events - at least not the events that I mentioned.
After a ton of fiddling and attempts at making a bare-bones version that still demonstrated the problem (which I was unsuccessful at doing), I figured out the root cause. Sadly, I did not figure out a workaround.
The Problem:
My plot wx.Panel was binding wx.MOUSE_LEFT_DOWN. It seems that this was preventing the parent wx.Frame window from giving focus to the Panel that held the plot and the legend.
The Solution:
I removed the bind to wx.EVT_LEFT_DOWN and that seems to fix the underlying issue. However, this is still not the ideal case because it causes two other problems:
I can no longer use my left mouse button on the plot. Not a big deal, I guess, because I can always bind right-mouse.
A user must first left-click on the plot area to give it focus before the mouse scroll or any keyboard shortcuts will work. This doesn't necessarily stem from not binding wx.EVT_LEFT_DOWN, but rather (I believe), from something that Windows does. See Focus-follows-mouse in wxPython? for a bit more info.
Failed Workaround:
I tried a workaround: adding code that sends the wx.EVT_LEFT_DOWN event to the parent but either that still didn't work or I was doing it wrong. Here's the left-click event handler that I tried:
def left_click(self, event):
print("left click!")
parent = wx.GetTopLevelParent()
wx.PostEvent(self.parent, event)
So anyway, this question is kinda solved. Hopefully what I've got here helps someone else out.
I am using a SearchCtrl with a dropdown menu and I'm having some trouble with the events. When I click the little arrow next to the search button, the EVT_SEARCHCTRL_SEARCH_BTN is triggered, which is not what I want. I only want the EVT_MENU_RANGE to be triggered after I clicked an item, and not also the EVT_SEARCHCTRL_SEARCH_BTN before i click it.
self.search_ctrl = wx.SearchCtrl(self.panel_1, -1,
style=wx.TE_PROCESS_ENTER)
self.search_menu = wx.Menu()
self.search_items = {"text1":"value1", "text2":"value2"}
for txt in self.search_items:
self.search_menu.Append(-1, txt)
self.search_ctrl.SetMenu(self.search_menu)
self.Bind(wx.EVT_SEARCHCTRL_SEARCH_BTN, self.search, self.search_ctrl)
self.Bind(wx.EVT_MENU_RANGE, self.onSearchMenu)
Although I should probably add id's to the menu bind, this isn't causing the problem. The code works as expected when I comment out the search button bind.
UPDATE
Apparently this isn't a problem, but a 'feature' of the searchctrl. I tried the wxpython demo and the menu also showed up if I just clicked the search button, and not the arrow. It is apparently one button, instead of the two i thought it was.
Is there a way to accomplish my original request? Do i have to manually modify a textctrl, or is there an other solution?
All the examples I've seen suggest you need to specify a range of IDs when you call your menu bind.
Maybe by default it binds to something unexpected... ?
Edit - In light of your update, it seems likely that you're going to need to make a custom control to me..
I am creating a Project Manager using wxPython it has a splitter window. On one side is a tree that shows the names of and opens the files and on the other size is a textctrl that is used to edit the file.
One problem I am having is that I would like it to go back 4 spaces when SHIFT and TAB are pressed, I have code working that add's 4 spaces when TAB is pressed.
I am also have a problem that when I add a file that is in a different folder to my programs cwd the tree adds a new node and the file appears under this node and I am struggling to get the tree to save to a file.
Also I would like to know how to add an icon to an item in the tree from an external png file.
I would appreciate any help that could be given with either of these problems.
To catch multiple keys, you either need to catch EVT_CHAR or use an accelerator table. The latter is easier while the former may give you more control. Here are a couple tutorials for you:
wxPython: Catching Key and Char Events
wxPython: Keyboard Shortcuts (Accelerators)
I don't know use WxPython and so don't have much idea about it. But in general what you can do is whenever a key is pressed, call a callback function and you could get the time when the key was pressed. save it somewhere. And when the next key is pressed, get the time. compare both times, if there's not much significant delay (you can decide the delay), it means that both the keys were pressed simultaneously (although they were not).
I'm using the new ttk.Notebook widget available in Python 2.7 and Python 3.1.
I'm struggling with the following tasks:
How to change the font associated with notebook tab captions. I want to use a named font object whose size a user controls. (Could a ttk.Style help me here?)
How can I bind to tab specific keyboard focus (<FocusIn>), mouseover events (<Enter>), and rightclicks (<Button-3>). I have a total fail trying to bind to tab specific keyboard focus and mouseover events. I can bind to a <Button-3> rightclick, but I can't figure out how to determine the tab a user clicked on. Using .identify( event.x, event.y ) returns the string 'label' vs. a widget reference.
Is there a way to give tabs an id (the documentation hints at this via tab_id) so we can reference tabs independent of their physical position in an array of tabs?
Thank you,
Malcolm
We're actually answering these questions in the Tkinter mailing list; in fact, I have mixed feelings about saying anything in Stackoverflow apart from, "See the mailing list". It's surely fair to note, though, that this answers the question about fonts, and this heads a thread on tab events.