How do I stop gtk.Entry from losing focus on arrow keypress? - python

I'm writing a Python GTK app that uses a gtk.Entry widget to forward keypresses to multiple other widgets. Unfortunately, it seems like GTK has a default binding that switches widget focus on the up and down arrow keys out of the Entry widget.
I want to disconnect this key-based focus switching, but leave mouse based focus switching in place. I can't seem to find where in the API I'd do this.
Any suggestions?

Return True from a handler for the key-press-event signal to prevent the default handling: http://www.pygtk.org/docs/pygtk/class-gtkwidget.html#signal-gtkwidget--key-press-event

Related

Tkinter Listbox - How to disable arrow key selection?

I have a Python 3.7 tkinter GUI, and within the GUI I have implemented up-down arrow key controls for the main part of the application. Next to it I have a list box that also controls the application but in a different way, and by default AFTER a listbox selection has been made the listbox selection will scroll with up and down arrows. So, after I've used the list box in the app, the arrow key triggers an up arrow event in both the main part of the application and in the list box. This triggers my application to respond in the change in list box selection by loading new data into the main app. This is obviously unacceptable.
How can I disable the arrow key controls feature of tkinter's
ListBox?
I've tried configuring the listbox to not take focus, but this doesn't seem to disable the feature.
Edit:
I solved this by binding the list box's FocusIn event to a function that immediately focus's something else. This is far from ideal, as the code now focus's in then changes focus for no reason. If there is a way to disable focus on a widget completely or disable the list box key bindings that would be a preferred solution.
from tkinter import *
class App:
def __init__(self):
self.root = Tk()
self.dummy_widget = Label()
self.lb = ListBox(master=self.root)
self.lb.bind("<FocusIn>", lambda event: self.dummy_widget.focus())
# Additional setup and packing widgets...
if __name__ == '__main__':
mainloop()
This seems very "hacky", although it does the job perfectly.
How can I disable the arrow key controls feature of tkinter's ListBox?
Create your own bindings for the events you want to override, in the widget in which you want them overridden. Do anything you want in that function (including nothing), and then return the string break, which is the documented way to prevent events from being processed any further.
For a more extensive description of how bindings work, see this answer to the question Basic query regarding bindtags in tkinter. It describes how a character is inserted into an entry widget, but the mechanism is identical for all events and widgets in tkinter.

Tkinter: What's the difference between grab and focus?

In tkinter I am creating a Toplevel widget to prompt the user with "Are you sure you want to exit?" every time they try to exit my application. While this is happening, I want the Toplevel widget to have full focus of my application and the user to be unable to click anything on the root window, if possible.
While trying to figure out to do this, I discovered grabs and the ability to set the focus of the application. What is the difference between these two things?
Thanks in advance.
Focus means that your window will receive all keyboard events until some other window gets the focus. A grab tells the window manager that your window should have the focus until you explicitly tell it that it is allowed to take it away (ungrab).

Qt - Temporarily disable all events or window functionality?

I have a Qt program with many buttons, user-interactable widgets, etc.
At one stage in the program, I would like all the widgets to temporarily 'stop working'; stop behaving to mouse clicks and instead pass the event on to one function.
(This is so the User can select a widget to perform meta operations. Part explanation here: Get variable name of Qt Widget (for use in Stylesheet)? )
The User would pick a widget (to do stuff with) by clicking it, and of course clicking a button must not cause the button's bound function to run.
What is the correct (most abstracted, sensible) method of doing this?
(which doesn't involve too much new code. ie; not subclassing every widget)
Is there anything in Qt designed for this?
So far, I am able to retrieve a list of all the widgets in the program (by calling
QObject.findChildren(QtGui.QWidget)
so the solution can incorporate this.
My current horrible ideas are;
Some how dealing with all the applications events all the time in one
function and not letting through the events when I need the
application to be dormant.
When I need dormancy, make a new transparent widget which recieves
mouse clicks and stretch it over the entire window. Take coordinates
of click and figure out the widget underneath.
Somehow create a new 'shell' instance of the window.
THANKS!
(Sorry for the terrible write-up; in a slight rush)
python 2.7.2
PyQt4
Windows 7
You can intercept events send to specific widgets with QObject::installEventFilter.
graphite answered this one first so give credit where credit is due.
For an actual example in PySide, here's an example you might draw some useful code from:
my_app.py
from KeyPressEater import KeyPressEater
if __name__ == "__main__":
app = QApplication(sys.argv)
eater = KeyPressEater()
app.installEventFilter(eater)
KeyPressEater.py
class KeyPressEater(QObject):
# subclassing for eventFilter
def eventFilter(self, obj, event):
if self.ignore_input:
# swallow events
pass
else:
# bubble events
return QObject.eventFilter(self,obj,event)

wxPython Whole Window Focus Event

With wxPython, how does one trigger an event whenever the whole window goes into/out of focus?
To elaborate, I'm building a serial terminal GUI and would like to close down the connection whenever the user doesn't have my application selected, and re-open the connection whenever the user brings my app back into the foreground. My application is just a single window derived from wx.Frame.
The correct answer for this case is to use an EVT_ACTIVATE handler bound to the frame. There will be an event whenever the frame is activated (brought into the foreground relative to other windows currently open) or deactivated. You can use the event object's GetActive method to tell which just happened.
as WxPerl programmer i know there is
EVT_SET_FOCUS(
EVT_KILL_FOCUS(
if you initialize this event by listening to the frame as first parameter it should work as in Perl since the API is almost the same
Interesting article at http://www.blog.pythonlibrary.org/2009/08/27/wxpython-learning-to-focus/
Gist of it: wx.EVT_KILL_FOCUS works fine, but wx.EVT_SET_FOCUS behaves a little oddly for any panel containing widgets (the child's set-focus prevents the panel's set-focus event from firing as expected?)
In addition to what these fellows are saying, you might also want to try EVT_ENTER_WINDOW and EVT_LEAVE_WINDOW. I think these are fired when you move the mouse into and out of the frame widget, although I don't think the frame has to be in focus for those events to fire.
# Hugh - thanks for the readership!

Tkinter: Listbox separators, disabled items, keyboard navigation?

I'm studying the Tkinter Listbox widget and have been unable to find solutions for the following functionality:
How can I create non-selectable horizontal separator items, eg. separators equivalent to the Tkinter Menu widget's .add_separator()? (Using chars like dashes and underscores looks awful).
How can I disable a specific item? I tried using .itemconfig( index, state='disabled' ) without success.
How can I enable keyboard navigation, eg. when a user's keyboard input automatically scrolls one forward to the closest item that begins with the text the user typed? Must I bind(<KeyPress>, ...) and manage this behavior myself?
Would some of the above functionality be easier to implement using a Text widget or the ttk.Treeview widget?
you cannot. The widget doesn't support that.
you can't disable certain items, the widget doesn't support a state attribute. That being said, you can monitor the selection and do the appropriate thing if the user selects something that is disabled, and use the item foreground to denote disabled-ness.
You will need to bind to keypress events and manage the behavior yourself. It's not particularly difficult, just a little tedious.
the text widget might be your best bet, though you'll have to add bindings to mimic the default bindings of the listbox.
Bottom line: Tkinter provides nothing that directly supports what you want to do, but the building blocks are all there. You'll just have to build it yourself.

Categories

Resources