The code below creates a single dialog window with 5 buttons. Each button is connected to onClick function. If I hit 'Enter' keyboard key one of the buttons is triggered and it onClick function is executed.
How to change the buttons properties so the buttons call for onClick function only when they are clicked and do not respond to Enter keyboard key?
from PyQt4 import QtGui
def onClick():
print 'button clicked'
dialog = QtGui.QDialog()
dialog.setLayout(QtGui.QVBoxLayout())
for i in range(5):
btn = QtGui.QPushButton('Button %03d'%i)
btn.clicked.connect(onClick)
dialog.layout().addWidget(btn)
dialog.show()
Set the default and autoDefault property of the QPushButtons to False. E.g.
btn = QtGui.QPushButton('Button %03d'%i, default=False, autoDefault=False)
What you are observing is the the QDialog's special handling of the enter key to trigger the default 'dialog action' (it is a common gotcha when using QDialog).
Related
I am trying to get the value of a combobox on a button click and process the value in the button click handler. However, the combobox.v_model seems to be updated correctly only after the button click handler has exited.
Here is what I did (code below):
enter string 'xxx' in the combobox when widgets show up
click on the button thereafter and fetch the value of combobox.v_model
Expected to retrieve 'xxx', but retrieved '' (empty string) instead
Is there a way to retrieve the combobox content with a button click immediately after input?
Note: when 'Enter' / 'TAB' is pressed before the button click, all works, but not if the button is pressed immediately after input in the combobox.
import ipyvuetify as vue
name = ''
# vuetify combobox and button
combobox = vue.Combobox(label="Enter name", v_model="", items=[], autofocus=True)
btn = vue.Btn(children=['Process name'])
component = vue.Row(children=[
vue.Col(children=[combobox]),
vue.Col(children=[btn])
])
# --- event handler -------------------------
# Some processing of the combobox input needs to happen
# on a button click, but v_model is not updated
def on_button_clicked(widget, event, data):
print(f"btn clicked: {combobox.v_model=}")
name = combobox.v_model
print(f'btn clicked: {name=}')
# do some processing with name here
btn.on_event("click", on_button_clicked)
display(component)
Could be a bug in Vuetify: vuetifyjs/vuetify#12567 (also refer to this post on the ipyvuetify issue tracker).
Working in a secondary window with Tkinter, when I click on the "OK" button of the Messagebox message (Record insert correctly), this secondary window disappears and is hidden at the bottom of the taskbar. So immediately click "OK" in the Messagebox, I'll find myself automatically on the main window. I don't get errors
How can I not hide the secondary window in the taskbar and then stay inside the secondary when I click the "OK" button of the Messagebox? What should I write in the "Insert?"
Code Windows Main:
window=Tk()
window.title("main")
window.attributes('-zoomed', True)
Code Windows Secondary
from aaa import bbb
def form_secondary():
root = tk.Toplevel()
root.title("secondary")
root.geometry("1920x1080+0+0")
root.config(bg="white")
root.state("normal")
Function that launches MessageBox
def insert():
if aaaa() == "" or bbbb.get() =="" or cccc.get() == "" or ddddd.get() == "" or eeee.get() == "" or fffff.get() == "":
messagebox.showerror("There is some empty field. Fill out all the fields")
return
db.insert(aaaa.get(), bbbb.get(), cccc.get(), ddddd.get(), eeee.get, fffff.get())
messagebox.showinfo("Record insert correctly ")
clearAll()
dispalyAll()
You can keep a child window on top of its parent window by making the child window a transient window of parent window.
Since creation of window (in main script) and root (inside form_secondary() in another script) windows are in different scripts, you cannot refer window inside form_secondary() directly. One of the way is to pass window to form_secondary() as an argument:
def form_secondary(parent):
root = tk.Toplevel(parent)
root.title("secondary")
root.geometry("1920x1080+0+0")
root.config(bg="white")
root.state("normal")
# make this window a transient window
root.transient(parent)
And then pass window as an argument when calling form_secondary() in main script:
...
window=Tk()
window.title("main")
window.attributes('-zoomed', True)
...
# assume it is called inside a function
def some_func():
...
form_secondary(window)
...
...
Update: if it is called via a menu item, then use lambda.
For example:
editmenu.add_command(label='Database', command=lambda: name.form_secondary(window))
I am using QFileDialog module, and I encounter a problem: how do I know which button is clicked (save or cancel) in the popup window when using QFileDialog.getSaveFileName in PyQt5:
The QFileDialog::getSaveFileName() method returns an empty string if the file was not chosen, that is, when the cancel button is pressed, and instead a non-empty string when the save button is pressed:
filename, _ = QFileDialog.getSaveFileName()
if filename:
print("The save button is pressed")
else:
print("The cancel button is pressed")
I'm developing a small GUI application which is required to work with a wireless presenter pointer, which has only two keys: left arrow and right arrow. I can bind keyboard event "Left" and "Right" to the root (the main window) and call a function, so most part of my application works fine.
But when I need to pop up a message box with tkMessageBox to show some information, the only way to click "OK" button with keyboard is to press "space", which is not there on my presenter pointer. It means when such a message box is popped up, the presenter have to go to the computer to either click the "OK" button with mouse, or "space" key with keyboard.
Is there any way allowing me to temporarily bind "left arrow" or "right arrow" to the "OK" button when such a message box is popped up and then restore the binding of both the keys back to there original on_click function?
As the tkMessageBox is not an object but a tcl call, you cannot overload bindings that easy. Just subclass Tkinter.Frame to get an object where keys can be bound.
Subclassing could nevertheless follow the look and feel of a MessageBox.
e.g.
#!/usr/bin/python
import Tkinter
class MyBox(Tkinter.Toplevel):
def __init__(self, *args, **kwargs):
Tkinter.Toplevel.__init__(self, *args, **kwargs)
self.__text = Tkinter.StringVar()
self.__text.set("Initialized Text")
Tkinter.Label(self, textvariable = self.__text).grid(row=0, column=0, columnspan=3, sticky=Tkinter.NW+Tkinter.SE)
Tkinter.Button(self, text="OK", command=self.release_func).grid(row=1, column=1, sticky=Tkinter.NW+Tkinter.SE)
self.bind_all("<KeyRelease>", self.release_func)
self.grid()
self.focus_set()
def set_text(self, text="NoText"):
self.__text.set(text)
self.focus_set()
def release_func(self, event=None):
# event=None necessary as we also use button binding.
self.destroy()
root = Tkinter.Tk()
messagebox = MyBox()
messagebox.set_text("Show this message")
root.mainloop()
i know "toggled-or-untoggled" event is not exist but i need to use event like this. is there a event to do task when button is "toggled" and "untoggled". i don't want use "clicked" event because ToggleButton can be toggled or untoggled without clicked
Thanks
example
def foo(obj):
if obj.get_active():
print("toggled")
else:
print("untoggled")
mybtn = gtk.ToggleButton()
mybtn.connect("toggled-or-untoggled", foo)
According to the docs -
When the state of the button is changed, the “toggled” signal is
emitted.
So, ideally, mybtn.connect("toggled", foo) should work.
Here's a short GTK2+ / PyGTK demo; it should be easy enough to adapt to GTK3, if necessary.
The GUI contains a ToggleButton and a plain Button. The ToggleButton's callback just prints the state of the button whenever it's toggled, either by the user clicking on it or by other code calling its set_active method. The plain Button prints a message when it's clicked, and it also toggles the ToggleButton.
#!/usr/bin/env python2
from __future__ import print_function
import pygtk
pygtk.require('2.0')
import gtk
class Test(object):
def __init__(self):
win = gtk.Window(gtk.WINDOW_TOPLEVEL)
win.connect("destroy", lambda w: gtk.main_quit())
box = gtk.HBox()
box.show()
win.add(box)
self.togglebutton = button = gtk.ToggleButton('toggle')
button.connect("toggled", self.togglebutton_cb)
box.pack_start(button, expand=True, fill=False)
button.show()
button = gtk.Button('plain')
button.connect("clicked", self.button_cb)
box.pack_start(button, expand=True, fill=True)
button.show()
win.show()
gtk.main()
def button_cb(self, widget):
s = "%s button pressed" % widget.get_label()
print(s)
print('Toggling...')
tb = self.togglebutton
state = tb.get_active()
tb.set_active(not state)
def togglebutton_cb(self, widget):
state = widget.get_active()
s = "%s button toggled to %s" % (widget.get_label(), ("off", "on")[state])
print(s)
Test()
typical output
toggle button toggled to on
toggle button toggled to off
plain button pressed
Toggling...
toggle button toggled to on
plain button pressed
Toggling...
toggle button toggled to off
plain button pressed
Toggling...
toggle button toggled to on
toggle button toggled to off