Python / Tkinter keep window in back - python

In Python with Tkinter, if you use the command:
`sometkapp.overrideredirect(True)`
It will make a Tkinter window that doesn't have a border from the window manager; however, at least on my windowing system, the Tkinter window then stays on top of all the other windows.
Is there a way to send a Tkinter window to the back, so that it always stays under all other open windows?

In some system window manager decides which window is on top or on bottom.
Using overrideredirect(True) you resign with its services - on some systems this meen no drawing border, no moving on top/on bottom (probably no refreshing window), no sending events (key pressed, mouse move).
I think you can do nothing with this using Tkinter or even pure Python. Maybe other module could do something.

Related

background window and main window tkinter

I'm learning Tkinter and just had a doubt.
Is there any method that prevents me from working with the window in the background until I close the main window? I saw that there is an argument about this here, but I ended up losing it and decided to ask.
Yes, it is possible (IIUC) and if I do understand correctly you simply want to block user for accessing other windows while your window is open. It has a slight flaw in that if user does a lot of alt-tabbing they may get keyboard focus on some other window but only the keyboard, as soon as they do anything with mouse they should get back to the main window. This can be handled using some module like keyboard to listen for global keyboard input but also perhaps it could be done using Windows API but for a tkinter only solution that is/should be effective enough you can use this:
import tkinter as tk
def check_focus():
if root.focus_get() is None:
root.focus_force()
root.after(100, check_focus)
def create_shield():
shield = tk.Toplevel(root)
shield.attributes('-topmost', True)
shield.attributes('-fullscreen', True)
shield.attributes('-alpha', 0.01)
shield.overrideredirect(True)
shield.bind('<FocusIn>', lambda _: root.focus_force())
root = tk.Tk()
root.attributes('-topmost', True)
create_shield()
check_focus()
root.mainloop()
First there is the after "loop" that checks for focus to see if the window has any, this prevents some attempts of trying to alt-tab away but enough attempts may cause some kind of timeout and the window will get out of focus.
The other part is a "shield" that simply is another fullscreen window that is almost completely invisible (on other OS the attribute name may be -splash instead of -alpha) and just keeps it in top to assist in focusing on the main window.
Or just make the window fullscreen and topmost (again the issues with keyboard focus on other windows but now user has no issues whatsoever with accessing the other windows except they wouldn't see what they are typing) and this requires to implement some button to close the window (currently doable by alt+f4 or shutting down the computer or killing the process via run without looking at what you are typing and perhaps some other way I haven't thought about, but for user convenience probably a button should be made that would simply destroy the window):
import tkinter as tk
root = tk.Tk()
root.attributes('-topmost', True)
root.attributes('-fullscreen', True)
root.mainloop()

Tkinter unresponsive when running input(), worse in IDLE

Hello I found a little issue with using the turtle library and python's IDLE. Observe the following code written in Python 3.5.2:
import turtle
turtle.Turtle()
input("Try moving/resizing the window in IDLE. Press enter than try again.")
Before pressing enter to give your input, the turtle window will be labeled as unresponsive and not allow the user to resize it. That is, if it's ran with IDLE. However, it works perfectly fine when ran through something such as the windows command prompt or PowerShell.
If ran through IDLE, after the user presses enter the window may then be freely moved and resized with no issues. This comes with the drawback that we're no longer inside the script but back to python's shell. Of course, we can still interact with the turtle via the shell but this isn't what I want in my actual application. My main program uses input() to ask the user if they wish to move/rotate and by how much. This remains in an endless loop until the user enters a phrase such as 'quit' to end the program. I will note, even with IDLE the turtle still moves and is drawn correctly. The problem is that the window itself becomes unresponsive. The contents is all correct.
I'm very curious to as of why only IDLE is giving me such behavior... Not only that, is there a way I can keep turtle window from being unresponsive and still make use of input() and the like? Or perhaps there is an alternative I did not think of? My research has lead me to believe this has something to do with TkInter. That would explain why it only works outside of IDLE.
Below is an image that shows my predicament.
Unresponsive turtle window
As you suspected, the primary issue is with tkinter, not specifically with the turtle app that uses tkinter. I first reproduced in IDLE with a bare tk window.
import tkinter as tk
root = tk.Tk()
input('prompt: ')
I then did the above a line at a time in 3.5.2 running interactively in Command Prompt on Win10. The second line displays a bare window, add a entry in TaskManager, and adds a Python icon to the task bar. Clicking back and forth between CP and Tk causes the the corresponding window and icon to get the 'active' appearance. The window border shifts from gray to black, whereas the icon background shifts from black to gray.
While typing the input statement, but before hitting return, the Tk window shows 'not responding' (after a couple of seconds) both on the title bar and in TaskManager. The mouse over the inside of the window becomes the blue busy circle. The window becomes 'active' as described above, and can be moved, but cannot be resized and cannot be closed normally (clicking on [X] brings up the "Not responding, close or wait?" box.
When the statement is Entered, the tk window becomes normally responsive again. As soon as the 'user' enters anything, the tk window becomes unresponsive in the manner described above, until entry is completed with Enter.
If you retry in CP and enter some characters without hitting Enter, do you see the same unresponsiveness?
Differences in IDLE's shell: creating root puts a new entry in TaskManager, but the new window is attached to the IDLE icon. While the input statement is being written, the Tk window remains normally responsive. So at this stage, IDLE is better. When the input() statement is Entered, the Tk window becomes, as you noted, completely unresponsive (cannot move) even before any entry. This part is worse.
I tried one further experiment: running IDLE with the -n ('no subprocess') option.
C:\Users\Terry>python -m idlelib -n
In this mode, there is no problem that I could detect (unlike CP). This was still true when I ran turtle. You can ignore the deprecation warning for now.
Comment 1: IDLE is designed for development and learning, not for production execution. But it can be used for the latter if there is an advantage to doing so. You would just have to check that using -n does not introduce any other problems, or rather, that turtle and your code do not interfere with IDLE when running in the same process.
Comment 2: GUI programs usually do not use input and print. They are usually run without a console to interact with. If input() is used, even in the Windows console, user should not touch the window before responding to a prompt.
Comment 3: GUI programs usually use GUI widgets instead to fetch and display info. Turtle makes this more difficult, but not impossible, as demonstrated by turtledemo. You might be simplify and adapt the code in turtledemo/main.py.

How to set tkinter window focus out?

I am trying to do make a virtual keyboard using tkinter. Is there any method that allow tkinter window focus out? For example in java we can have setFocusableWindowState(false)
Thank you very much for your help.
I believe you can accomplish what you want with tkinter, but it's not about not getting focus. I don't think, that other GUI tools will make it any easier.
It's part of operation system, or more precisely window manager to give focus to some window, when it is clicked. So, in case of virtual keyboard:
User has focus in text editor (for example).
User presses a button on your virtual keyboard.
OS/Window manager gives focus to your keyboard window and sends mouse click event to the GUI library (tkinter).
Here you need to identify where was the focus before your window got it, i.e. get the text editor window handler somehow.
Send the button press event to that window and return focus.
Repeat.
You'll use tkinter to draw the keyboard window and handle mouse clicks/touches on virtual keyboard keys. But you'll need to work with OS/Window manager to identify other windows by handlers and send keypress events to them. May be you will be able to prevent focus switch by working with OS/Window manager, but it's not tkinter or other GUI library functionality.

Pass clicks through Tkinter window? Mac OSX

Is there a way to make a Tkinter window unclickable? Meaning that any input that should be caught by the handler are redirected to whatever window is behind it? If not in Tkinter, would there be a way in PyQt or wxPython? My goal is to have a handler catch keyboard events while still letting them input into the windows behind. I don't need to catch clicks but that would be nice to have if possible.
My current plan:
A Tkinter window with a geometry of 10000x10000, alpha of 0 and topmost set to true. The frame will catch all keyboard & mouse events and when anything is entered the frame will catch it, hide the Tkinter window using an apple script function which is run from terminal with osascript, use autopy to simulate whatever was entered such as a click/keyboard event and unhide the window again. Does this even sound viable?
When I have the time I will test out this idea and post if it works. I'm thinking computation speed will be an issue here.

How can I get a tkinter window to display in LINUX

I am trying to follow along in the book Python Programming for Kids. I am working with a group of neighborhood kids and to reduce the cost we are using the Raspberry Pi as our computer. I am a Windows guy and the GUI builder of choice for me is WxPython. I am trying to get ready for next weeks class and have run into a problem. I have entered the code below
from tkinter import *
tk = Tk()
btn = Button(tk,text = 'click me')
btn.pack()
according to the book the second line is supposed to create a window (frame I think in the Wx world) and the third line defines a button object and the fourth inserts it in the window.
However, this is not working and I have not been able to figure out why. tkinter is imported and the tk object has lots of methods/properties visible when I type dir(tk) so I know that we have tkinter on the Pi's.
Any insight would be appreciated.
You have to run the windows system event loop and process events. This means the last command in your program should be tk.mainloop(). The X Windows System operated in a similar manner to Windows. The system dispatches event messages whenever something happens like the mouse moving, a button being clicked or a window needs redrawing and so on. On Windows you would have to 'pump the message queue' using GetMessage() and DispatchMessage(). With Tkinter this is handled in the mainloop() function (for both Windows and X).

Categories