I have a Dialog Window with a TreeView and two Buttons (Gtk.ResponseType.CANCEL and Gtk.ResponseType.ACCEPT). I can't find how to activates the ResponseType.ACCEPT button when I press Enter inside the Gtk.TreeView. I set cant_datault on desired button and set_default on GtkDialog but Gtk.TreeView doesn't have an activates default method.
Is there any way I can do this?
The quickest way I could find would be to use the "row-activated" signal within the TreeView. This is activated whenever you press Enter, double-click an item or press the Spacebar.
So for example:
treeview.connect("row-activated", lambda a, b, c: dialog.response(Gtk.ResponseType.ACCEPT))
I've used lambda to create the anonymous function, but if you have anything else that needs to run at the same time, you can swap it for a proper function.
Just be aware that if you also change your default response in the future, you'll need to update this function as well.
Related
I'm trying to create an Undo and Redo Button inside a GUI App using PyQt5 and Python 3.7.
When the Undo and Redo Buttons are clicked, the Key Sequences "Ctrl+Z" and "Ctrl+Y" should be executed respectively. Ive superficially gone through the documentation of QShortCut and QKeySequence but they seem to be designed for detecting key sequences and not triggering them. So how do I implement these buttons?
As per eyllanesc's comment, I'm adding this to better explain what I am trying to achieve.
self.undoButton = self.findChild(QtWidgets.QPushButton, 'undoButton')
self.undoButton.clicked.connect(self.undoButtonPressed)
self.anyPlainTextEdit = self.findChild(QtWidgets.QPlainTextEdit, 'anyPlainTextEdit')
# Function to Execute Key Sequence
def undoButtonPressed(self):
# Execute Ctrl+Z Key Sequence
I'm wondering if this is even possible.
If not, should I maintain Previous and current values of the PlainTextArea in separate variables and set the value of the PlainTextArea accordingly?
You don't have to launch the shortcut to enable redo or undo, just call the slot redo() and undo() when the buttons are pressed:
self.undoButton.clicked.connect(self.anyPlainTextEdit.undo)
self.redoButton.clicked.connect(self.anyPlainTextEdit.redo)
I have a tk.Button(..., command=_on_button_click).
Once it is clicked, I want to know whether the Shift key is currently held down.
But the _on_button_click is called without any event object or similar for me to check it
Assuming a button named button and a handler named shift_click, you can use the bind method:
button.bind("<Shift-Button-1>", shift_click)
Of course, you will probably also want one without shift click:
button.bind("<Button-1>", not_shift_click)
I am making a box that is similar to the tkMessageBox. There are two simple behaviors that I want to the box to have. First I want the button to be selected automatically when the window opens, and second I want to be able to press enter to push the button. Sounds simple and I realize that I could use the tkinterMessageBox to do this same thing, but this is a stepping stone, and I would like to know how to do this in the future for other things.
The current behavior of the window below is that it opens, and if I press tab it will select the button, but then i can only press the button with the mouse. Again the desired functionality is to have the button selected right away and be able to press the button with the enter key.
import Tkinter, tkMessageBox
from Tkinter import *
def closewindow():
Messagebox.destroy()
Messagebox=Tk()
l3=Label( Messagebox, text="This is your preview! Align camera then press ESC")
b3=Button(Messagebox, text="Okay", command=closewindow)
l3.grid(row=1,column=1)
b3.grid(row=2,column=1)
Messagebox.mainloop()
You can actually do this with just two lines of code:
b3.bind('<Return>', lambda _: closewindow())
b3.focus_set()
The first binds the button to the Enter key and the second sets the application's focus on the button.
Note that I had to use a lambda with the binding to handle the event object that will be sent to the callback. You could however change the definition of closewindow to handle this:
def closewindow(event=None):
Messagebox.destroy()
Now you can just do:
b3.bind('<Return>', closewindow)
For more information on bindings in Tkinter, see Events and Bindings over on Effbot.
I have the following problem when using tkinter to create a very simple window containing a matrix of buttons: When one of the buttons is clicked, the event handler changes the text of that button using the configure method on the button widget. This works. But I also want to change the text in one of the other buttons, which does not work. The method I use is that on creating the button, I store the object returned by the Button method before I use the grid geometry manager to place it. This object looks like ".123456789L" when printed and seems to be a pointer to the widget. I also use configure on this to change the button text. But somehow it seems to be wrong, because it works sometimes, and most of the times not. There's unfortunately no error message, just nothing happens when calling configure. I checked and it seems to be the correct pointer to the widget. Do I have to use a special way to affect a widget other that the one that called the event handler? These are the relevant parts of the code:
# CREATING THE BUTTONS:
buttons={} # global
for i in range(3):
for j in range(3):
button = Tkinter.Button(self,text='foo')
buttons[button]=(i,j)
button.grid(column=j,row=i)
button.bind( "<Button-1>", self.OnButtonClick )
# CHANGING BUTTONS:
def find_button(i,j):
"""Return the pointer to the other button to be changed when a button has been clicked."""
for button,key in buttons.items():
if key==(i,j): return button
def OnButtonClick(self,event):
print "You clicked the button",buttons[event.widget]
i,j=buttons[event.widget]
old_button=find_button(i,j) # This is simplified, I don't actually pass i,j, but other values. But I checked this and it returns the reference to the correct button. But this simplified version works the same way, just assume a different button that the one pressed would be returned.
old_button.configure(text = 'blabla') # THIS DOES NOT WORK
event.widget.configure(text = 'something') # THIS WORKS
I have the same problem and i solve it with:
buttons[button]=(i,j,button)
and in the function OnButtonClicK:
i,j,old_button=buttons[event.widget]
old_button.configure(text = 'blabla') # THIS DOES NOT WORK
I am using GtkMenuToolButton and it has a button and a menu. When you click on the arrow the menu is opened. I'd like to make the button open that same menu as well. Simply emitting "show-menu" in the "clicked" callback did not work. Please help how to make this work.
I have currently ended up doing this:
Instead of GtkMenuToolButton I have GtkToolItem with custom content
In custom content I have GtkMenuButton
Inside that one, I delete the default GtkArrow and replace it with 1x2 GtkGrid which has a Label + GtkArrow
As a whole it does what I want =)
When you create the menu, save a reference to it as self.tool_button_menu or something; then in the clicked callback, call
self.tool_button_menu.popup(None, None, None, None, 0, Gtk.get_current_event_time())
The first two Nones are the parent menu and the parent menu item (not applicable). The second two Nones are a positioning callback function (more on that in a minute) and data to pass to it. 0 is the mouse button if the menu was initiated by a mouse button press (but you should pass 0, because I think in your case it's either a mouse button release or a key press.) And the last parameter is the timestamp to give to the menu popup event.
Now the positioning function. It takes two parameters and returns three:
def positioning_function(menu, data=None):
# ...magic...
return x, y, push_in
push_in should be True if you want the menu to be repositioned so that it always fits on the screen. Seems like a good idea. You can get good values for x and y by looking at the tool button's get_allocation(); read the x, y, width and height attributes of that object and calculate a nice place to put the menu.