Make a tkinter window appear over all other windows - python

#!/usr/bin/env python
# Display window with toDisplayText and timeOut of the window.
from Tkinter import *
def showNotification(notificationTimeout, textToDisplay):
## Create main window
root = Tk()
Button(root, text=textToDisplay, activebackground="white", bg="white", command=lambda: root.destroy()).pack(side=LEFT)
root.update_idletasks()
# Remove window decorations
root.overrideredirect(1)
timeOut = int(notificationTimeout*1000) # Convert to ms from s
## Run appliction
root.after(timeOut,root.destroy)
root.mainloop()
The above code creates a notification, with a timout. However on windows - the notification does not automatically pop up above all other present windows automatically. One has to click on the kill button (the text), and focus it the first time, after which the root window will be displayed above all other windows.
Is there a way to make the notification automatically appear above all other windows - on windows?
It seems to work on linux just fine (ubuntu 9.10).

According to this message you should be able to add the following after root.overridedirect(1). A quick test here suggests it should work for you.
root.wm_attributes("-topmost", 1)

Related

In tkinter when I create a second window using Toplevel then both window appear in under same program, how to make them appear different?

I have made a tkinter based windows application that in which 2 window get created which show some simple global variable that are displayed in both window and can be changed by entering value in any window too, everything is working fine only problem is taskbar label comes grouped together in windows taskbar which makes it difficult to navigate between two windows, it there any way both windows appear separately in windows taskbar.( NOT by using windows inbuilt option to make all taskbar labels separate)
this is my code it's just a basic code to show my problem.
from tkinter import ttk
from tkinter import *
root = Tk()
root.geometry("200x200")
root.title("root win 1")
Label(root, text='this is first window').pack()
def extra_root():
new_root = Toplevel(root)
new_root.title("root win 2")
new_root.geometry("200x200")
Button(new_root,text='this is 2nd window' , command=None).pack()
new_root.mainloop()
#to create 2nd window
Button(root, command=extra_root).pack()
root.mainloop()
this is my how it comes currently
this is how I want it to appear (this is achieved by using windows inbuilt feature to make all taskbar label to appear separately)

tkinter wiget.bind('<Activate>', callback) not working

I've been trying to create a message box when a button turns from disabled to active but when the button actually turns from disabled to active for some reason my callback is not even being called I've tried to get it working so for quite a bit of time now and I'm stuck.
Here is an example of the problem:
from tkinter import *
from tkinter import Tk
def disable_and_activate():
b.config(state = DISABLED)
b.config(state = ACTIVE)
def is_working(event):
print('working')
root = Tk()
b = Button (root, text = 'click me', command = disable_and_activate)
b.pack()
b.bind('<Activate>', is_working)
root.mainloop()
Console:
the button is clicked but there's nothing printed on the console
The <Activate> event is not triggered when you set the state of the button to "active". The event is triggered when the window becomes the active window.
For example, when I run your code on my OSX machine, if I click on some other application to give it focus and then I click back to the tkinter window, the event will fire when the tkinter window becomes the active window.
This is explained in the canonical tcl/tk documentation which says this:
Activate, Deactivate
These two events are sent to every sub-window of a toplevel when they change state. In addition to the focus Window, the Macintosh platform and Windows platforms have a notion of an active window (which often has but is not required to have the focus). On the Macintosh, widgets in the active window have a different appearance than widgets in deactive windows. The Activate event is sent to all the sub-windows in a toplevel when it changes from being deactive to active. Likewise, the Deactive event is sent when the window's state changes from active to deactive. There are no useful percent substitutions you would make when binding to these events.
Here the problem was just the code inside the function , It seems like you needed to call EventGenerate('<<Activate>>') I also recommend adding 2 << and 2 >>
So I rewrote the code and its now working perfectly fine:
from tkinter import *
from tkinter import Tk
import tkinter
def disable_and_activate():
b.configure(state=tkinter.DISABLED)
b.configure(state=tkinter.ACTIVE)
b.event_generate("<<Activate>>")
def is_working(event):
print('working')
root = Tk()
b = Button (root, text = 'click me', command = disable_and_activate)
b.pack()
b.bind('<<Activate>>', is_working)
root.mainloop()

How to open the Touch Keyboard using python?

I'm woking on a project of a chatting app, using tkinter, running on python 3.7 and Windows 10 OS. One of the things I would like to add to my app, is an option of opening up the Windows's Touch Keyboard.
Although you can open the keyboard by pressing its button on the taskbar, I would like to give access to it from my app. My idea is to bind an Entry widget, used as the console line of my app, to an event, that whenever it occurrs, it makes the Touch Keyboard to pop up. The event I'll probably be using is '<FocusIn>', which means that the keyboard focus is moved to it. Here is a quick example of the mechanics:
def open_keyboard(event):
pass # open the Touch Keyboard
root = Tk()
console = Entry(root, font=('Verdana', 14), cursor='pencil', bg='red', fg='yellow') # creating console
console.pack()
console.bind('<FocusIn>', open_keyboard) # bind the console to the event
root.mainloop()
NOTICE: The Touch Keyboard IS NOT the On-Screen Keyboard. I don't want to use this keyboard, because it poppes up as a new window and not as a Toplevel window, which blocks my chatting app. More Importantly, it has no Emoji keyboard :)
A simple way to open the On-Screen Keyboard, is by running the following lines:
import os
os.system('osk')
I've been searching all over the internet for a solution, but they're all seem to be handling the On-Screen Keyboard. If someone knows how to help me or divert me to a source that explains how to handle it, he's more than welcomed to do so, because I'm stuck right now :/
Try this (explanation in code comment)
I think this directory will be the same on almost all Windows installations, still I'm looking for a way to make it path independent.
from tkinter import *
import os
root = Tk()
def callback(event):
# so the touch keyboard is called tabtip.exe and its located in C:\Program Files\Common Files\microsoft shared\ink
# here we run it after focus
os.system("C:\\PROGRA~1\\COMMON~1\\MICROS~1\\ink\\tabtip.exe")
frame = Frame(root, width=100, height=100)
frame.pack()
addressInput = Entry(frame, font = "Verdana 20 ", justify="center")
addressInput.bind("<FocusIn>", callback)
addressInput.pack()
root.mainloop()

Tkinter window hangs after restoring from system tray (using pystray)

I'm creating a Tkinter-based GUI in Python. I would like the window to hide to system tray when it is minimized (using pystray module). It hides, but it only appears on the screen and hangs, when I'm trying to restore it.
Here's what I have tried:
from tkinter import *
from PIL import Image
import pystray
def hide_to_tray(_event=None):
tray_icon = pystray.Icon("MyTrayIcon", title="My tray icon") # create the tray icon
tray_icon.icon = Image.open("app_icon.ico") # open the icon using PIL
tray_icon.menu = pystray.Menu(pystray.MenuItem("Open", lambda: tray_icon.stop(), default=True)) # create the menu
root.withdraw() # hide the window
tray_icon.run() # run the icon's main loop
# icon mainloop
root.deiconify() # when the icon mainloop had been stopped, show the window again
root.focus_force() # focus on it
root = Tk()
btn = Button(root, text="Sample button")
btn.grid()
root.bind("<Unmap>", hide_to_tray) # hide to tray on minimizing
root.mainloop()
How can I solve this problem?
1. Use infi.systray
It runs on a seperate thread and thus won't block, install it with pip:
pip install infi.systray
Don't call tkinter methods from the info.systray thread:
Since infi.systray runs on a seperate thread, you mustn't call tkinter methods directly in the callback functions that you pass to the systray icon on creation. Use a thread safe way (e.g. queue) to inform the main thread about events in the systray icon instead!
2. Don't run pystray and tkinter at the same time
You can't run them both because they block the running thread and both have to run on the mainthread.
See Osher's answer that only displays the system tray icon when the tkinter app is closed.

Closing a window in python 3.7.2 with tkinter

I've made a program in python with Tkinter that allows you to free draw and choose different colors. I decided to make a button that would close the window instead of clicking the exit button in the top right corner. My question is how do I make the window close when the button is pressed?
If you are using a main loop for your application, then you can use the .destroy() method to release all the resources associated with the window and close the application. You call this method within the command function for your button like so:
from tkinter import *
root = Tk()
frame = Frame(root)
frame.pack(side=LEFT)
button = Button(frame, text="Exit", command=exit)
button.pack()
root.mainloop()
def exit():
root.destroy()
That should close your window. Optionally, the destroy() method may also be used at the end of your main loop if the X button of your application won't close the window immediately.
See these examples for more info:
http://effbot.org/tkinterbook/widget.htm#Tkinter.Widget.destroy-method
http://effbot.org/tkinterbook/tkinter-hello-again.htm

Categories

Resources