Why doesn't Tkinter call the function bound to the root window? - python

I'm creating a desktop application using Tkinter GUI which uses Control+Alt+F1 hotkey. But unfortunately, Tkinter doesn't call the function, when I press these keys.
I've tried root.bind("<Control-Alt-Key>", function), and it works. I've even tried to use root.bind("<Control-Shift-F1>", function) - and it works, too.
try:
# for Python 3
from tkinter import *
except:
# for Python 2
from Tkinter import *
root = Tk() # create the root window
# create bindings for root window
root.bind("<Control-Alt-F1>", lambda event: print("Ctrl+Alt+F1 pressed!"))
root.bind("<Control-Shift-F1>", lambda event: print("Ctrl+Shift+F1 pressed!"))
root.mainloop() # start the mainloop
Why Tkinter doesn't react to the Control+Alt+F1 keypress?
PS. I'm using Windows 10, Python 3.7.2

Most likely, the bios, OS, or window manager you're running on is intercepting that event before it is sent to tkinter. A classic example is ctrl-alt-delete on windows, which cannot be trapped by ordinary programs.
If that is the case, there's nothing you can do in tkinter to work around that.

Related

Python tk - hide console window

I have prepared some tk application. It could be really simple like:
from tkinter import *
# create root window
root = Tk()
# root window title and dimension
root.title("Welcome to GeekForGeeks")
# Set geometry (widthxheight)
root.geometry('350x200')
# all widgets will be here
# Execute Tkinter
root.mainloop()
I have using some method to convert the app to the exe file.
What is important,
I'm not using and I cannot do it with pyinstaller py2exe etc. I also cannot use method with changing my app.py to app.pyw.
But my conversion to .exe is working correctly.
The question - is it even possible to hide/disable/resize(reduce the size) of my console window and make the application still working?
I'm not exactly sure how is it done in pyinstaller py2exe etc, so maybe is it possible to do it inside an application?
All right, to solve above problem install:
pip install pywin32
and add code before running your tk gui application:
import win32gui
import win32.lib.win32con as win32con
the_program_to_hide = win32gui.GetForegroundWindow()
win32gui.ShowWindow(the_program_to_hide , win32con.SW_HIDE)
Then you can run the main.py in console, the console will disappear and the gui app will be still visible.
In case when you use pyinstaller etc - you can convert the application without "--noconsole" argument.
When you run the .exe file the console will appear for a second, and disappear. But the gui app will be still visible and usable.
Hope it help somebody somehow :)
I think you should run your script using pythonw.exe instead of python.exe. See .pyw files in python program
Does this help if using Toplevel?
from tkinter import *
root = Tk()
root.title("Main Window")
root.geometry("200x200")
def launch():
global second
second = Toplevel()
second.title("Child Window")
second.geometry("400x400")
def show():
second.deiconify()
def hide():
second.withdraw()
Button(root, text="launch Window", command=launch).pack(pady=10)
Button(root, text="Show", command=show).pack(pady=10)
Button(root, text="Hide", command=hide).pack(pady=10)
root.mainloop()

python tkinter - Bind a "Global" key shortcut which can be triggered from outside the window

I am thinking if there is any way to bind "GLOBAL" key bindings to tk/ttk widgets
for example:
in this code:
import tkinter as tk
def output(lines = 'hehehehe'):
print(lines)
root = tk.Tk()
button = tk.Button(root, text ='HAHAHA', command = lambda:output('hahaha'))
button.pack()
root.bind('<Control-a>', output)
root.mainloop()
now, whenever i hit Control+A when the window is active, the function output() works..
But, when i start any other window and make this tk-window inactive, The key bindings doesn't work...
Is there any way to bind "GLOBALLY"?
Not possible, you cannot access global key-strokes within tkinter, you will have to use some other external library like keyboard, should be fairly easy.
First install the library with pip install keyboard, then:
import tkinter as tk
import keyboard
....
keyboard.add_hotkey('ctrl+a', output, args=('From global keystroke',))
root.mainloop()

Create 2 tkinter windows one of which 'blinks' open and closed

I'm trying to create 2 tkinter windows, one that stays constant(win1) and one that closes and reopens at a set interval(win2). Ultimately I will pass a list of coordinates for win2 to iterate through so that it will open in a different position each pass of the loop.
Below is the code I am using to try and do this. Currently I get this error:
_tkinter.TclError: can't invoke "destroy" command: application has been destroyed
invalid command name "4349633280<lambda>"
while executing
"4349633280<lambda>"
("after" script)
How can I do this? I am also open to using a different GUI if necessary.
import tkinter as tk
tk.NoDefaultRoot()
win1 = tk.Tk()
tk.Button(win1, text='Spam').pack()
v=[1,2,3,4,5,6]
for i in v:
win2 = tk.Tk()
win2.after(300, lambda: win2.destroy())
win1.mainloop()
To do this you cannot use lambda without a default argument, but you don't need it at all. Also you should use Toplevel instead of Tk to make the additional windows.
import tkinter as tk
tk.NoDefaultRoot() # this seems useless ...
win1 = tk.Tk()
tk.Button(win1, text='Spam').pack()
v=[1,2,3,4,5,6]
for i in v:
win2 = tk.Toplevel(win1)
win2.after(300, win2.destroy) # close child window in 300 milliseconds
win1.mainloop()
Actually you create the six windows almost at the same time and then schedule six tasks to destroy them. However you use same variable win2 for the six windows, therefore win2 finally references only to the last window. When the first schedule task is executed, win2 is destroyed. When the second schedule task is executed, it tries to destroy win2 but it is already destroyed which causes the exception.
Also you should use Toplevel for win2. It is not recommended to have more than one instance of Tk().
Below is an example to use after() to do what you want:
import tkinter as tk
win1 = tk.Tk()
tk.Button(win1, text="Spam").pack()
def blink_window(win2=None, n=6):
if win2:
win2.destroy()
if n > 0:
win2 = tk.Toplevel()
win2.after(300, blink_window, win2, n-1)
blink_window()
win1.mainloop()

How to close a running windows OS program using a button?

I'm making a simple GUI using Python 3.7.3 and tkinter to open and close windows applications. I'm not able to find a way to close a running program using an onscreen button. I need the 'close' button to do something else as well, hence the simply using 'x' button (which is next to the minimize and maximize) won't work for my case.
from tkinter import *
import os, subprocess
root = Tk()
root.geometry("300x300")
def OpenCalc():
app1 = os.startfile("C:\Windows\System32\calc.exe")
def CloseCalc():
os.close(app1)
# or
# os.closefile("C:\Windows\System32\calc.exe")
b1=Button(root, text="Open Calc", command=OpenCalc).pack()
b2=Button(root, text="Close Calc", command=CloseCalc).pack()
root.mainloop()

How to remove title bar in Tkinter program?

I am working on a project using Tkinter library for making a GUI. This GUI will be displayed on a touch screen using raspberry pi 3.
I want to prevent user from exiting or minimising the program.
Is there any way to disable or remove the title bar? Or is there a better way to achieve this?
Since you mentioned a raspberry pi I suppose you are using Linux. In this case you can use root.attributes('-type', 'dock') (assuming your Tk instance is called root). This way, your window will have no decoration (so no close or minimize buttons) and will be always on top. If you don't want it always on top, you can use type 'splash' instead. In any case, you will need to use focus_force to be able to get keyboard focus.
import tkinter as tk
root = tk.Tk()
root.attributes('-type', 'dock')
root.geometry('200x200')
tk.Entry(root).pack()
root.focus_force()
root.mainloop()
Otherwise, you can prevent the window from being closed by setting the 'WM_DELETE_WINDOW' protocol and redisplay the window each time it is minimized:
import tkinter as tk
root = tk.Tk()
def unmap(event):
if event.widget is root:
root.deiconify()
root.protocol('WM_DELETE_WINDOW', lambda: None) # prevent closing
root.bind('<Unmap>', unmap) # redisplay window when it's minimized
root.mainloop()
root = tk.Tk()
root.wm_attributes('-type', 'splash')
For more details go to this link: Remove titlebar without overrideredirect() using Tkinter?

Categories