Tkinter Text widget unusable after displaying a tkinter.simpledialog prompt - python

In Tkinter I find a small problem. I am unable to use an Entry/Text/Scrolledtext/any widget that the user can enter letters into after using a Tkinter simpledialog prompt. The entry widget works fine before using the prompt, but after the prompt I am unable to enter stuff into the widget. It's as though the widget becomes disabled. No exception is thrown. However, I can access the widget again once I click on another window and click on my Tkinter window again.
I have tried using the focus_get method on the entry widget. It doesn't work.
I have also tried doing entry.config(state='normal'). That doesn't work.
I could not think of anything else to try. Searching the web doesn't work; nothing relevant comes up.
Here's some example code:
import tkinter as tk
import tkinter.simpledialog as dialog
def get_string():
string = dialog.askstring("Title", "Prompt")
print(string)
root = tk.Tk()
entry = tk.Entry(root)
button = tk.Button(root, text="Get String", command=get_string)
entry.pack()
button.pack()
root.mainloop()
For the problem to show, you need to click on the button, and then try to use the entry widget; it doesn't work for me.
I am using Python 3.9.6, on macOS.
Edit: after a few people commented, this problem is probably specific to macOS Big Sur; this problem isn't there on Windows, OSX, or Linux.

So, I left the project alone for a while, and now I've updated to macOS Monterey and Python 3.10. With these updates, I now find the problem disappeared.

Related

How to remove the borders of a tkinter window without making it topmost?

I want to make a borderless widget with tkinter that lets the user decide if they want the application to show on top of other programs or not.
I'm aware that in order to remove the borders and the toolbar I can use the method root.overrideredirect(True), but this also makes the window topmost automatically, as it makes the window manager ignore the widget.
Because of this, the root.attributes("-topmost",False) and root.wm_attributes("-topmost", False) command don't work.
Is there a way to achieve what I need? For example, another method to hide the window manager decorations or some other way to hide/restore the widget when it loses the focus?
By the way, I'm using Linux Mint 20.2 Cinnamon v5.0.5 with Python 3.8.10.
from tkinter import *
root = Tk()
root.overrideredirect(True)
root.resizable(False, False)
root.geometry("420x100")
root.attributes("-topmost", False)
#root.wm_attributes("-topmost", False)
exitbtn = Button(root, text='Exit',command=root.destroy)
exitbtn.pack(side=BOTTOM)
root.mainloop()
EDIT:
After some search, I've found that root.wm_attributes('-type','splash') works exactly as I want. But it seems that this will only work on Linux. How could I achieve that on Windows?
I had the same question and this worked for me:
Tkinter, Windows: How to view window in windows task bar which has no title bar?
PS: I'm new here so I cannot comment.
Edit: It's for Windows I think. I haven't tried on Linux yet.

Tkinter destroy() freezes window, rather than closing it until the program terminates?

So I've been having problems with Tkinter for Python 3 on MacOS 10.15.5. Here's the reproducible code for my system:
import tkinter as tk
import tkinter.messagebox as msgbox
def quit():
root.destroy()
root = tk.Tk()
lbl = tk.Label(root,text="This is a label.")
ent = tk.Entry(root)
btn = tk.Button(root,text="Quit", command=quit)
lbl.pack()
ent.pack()
btn.pack()
root.mainloop()
for i in range(800000):
print(i)
After I press "quit", the for loop runs in the background, but the Tkinter window freezes (with the spinning wheel), until the for loop concludes. I'm trying to create a program that takes user input at the beginning and then runs code in the background, so you can see why I'd rather not have the GUI frozen the whole time.
I'm running this code from the terminal, but I get the same issue using IDLE. I've tried uninstalling and reinstalling several different versions of python (from the python website, since apparently that's the way to use Tk properly), and this problem persists.
Weirdly enough, I've seen that adding an input statement, rather than any other code, immediately after the mainloop, will cause the window to close, but I can't figure out why, and it wouldn't really work with my broader program.

Python script tkinter resolution and screenshot size effected when running pythonw.exe

I currently have a python script which launches a tkinter GUI instance, with a button that once clicked takes a screenshot.
When I run this script under python.exe, the tkinter resolution is fine and the screenshot captures the whole screen. However, when using pythonw.exe, the tkinter window resolution changes (button gets bigger for example) and the screenshot only captures a portion of the screen - the top left hand corner normally.
I need to use pythonw.exe in order to prevent the console window appearing.
Does anyone know why the tkinter window resolution and the screenshot capture is being effected? Presumably the effect on the resolution is why the screenshot capture is being reduced as well.
I am fairly new to Python, so any help with this would be greatly appreciated, below is snippet of the code for the tkinter window and the screenshot functionality. To reiterate this functionality runs completely fine under python.exe.
The screenshot functionality using ImageGrab:
callback1():
ImageGrab.grab_to_file('test.png')
The tkinter window:
master = Tk()
master.wm_attributes("-topmost", 1)
master.title("Report")
master.configure(background='white')
master.iconbitmap(default='icon.ico')
master.resizable(0, 0)
frame1 = Frame(master, bg='white')
frame1.pack(side=BOTTOM, fill=X)
button1 = Button(frame1, compound=BOTTOM, width=307, height=82,
image=photo1, bg='white', command=callback1)
button1.pack(side=TOP, padx=2, pady=8)
I have now fixed this. It seems it was related to the compatibility settings for pythonw.exe in Windows. Changing the following fixes the image capture, but also the tkinter window resolution:
Go to your python directory (c:/python27/ for me)
Right click python.exe and select properties
Select the compatibility tab
Press the "Change settings for all users" button
Check the "Disable display scaling on high DPI settings" box
Credited by this post:
Python Imaging Library fails to grab whole screen
Hopefully this helps someone with the same issues. It does beg the question as to how this can be done automatically, as for users of a python application it is not user-friendly for them to have to change these settings.

How to 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 - the tk window is not displayed nor is there a button on the screen 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.
Again, after entering this code nothing visible happens. I deleted the code relating to creating the button and still nothing happens so I am not sure where to start diagnosing the issue I have Googled for information and found nothing useful
Any insight would be appreciated.
I did ask this question on superuser but there is no Tkinter tag so . . .
humm do I need a
tk.pack()
statement - I will report back.
No, you do not need tk.pack(). What you do need is start the event loop. The event loop, as it's name suggests, is a loop that processes events. Everything in Tkinter happens as a response an event, including the actual drawing of a widget or window on the screen.
As the last line in your file, add the following:
tk.mainloop()
I encourage you to not do the import the way you are doing. I know a lot of tkinter tutorials do it that way, but it's a bad thing to do. Instead, do it like this:
import tkinter as tk
root = tk.Tk()
btn = tk.Button(root, text='click me')
btn.pack()
root.mainloop()
It requires typing three extra characters for every widget, but in exchange you get code that is easier to maintain over time.
PEP8 is the official python style guide, and it explicitly recommends against wildcard imports:
Wildcard imports (from import *) should be avoided, as they
make it unclear which names are present in the namespace, confusing
both readers and many automated tools. There is one defensible use
case for a wildcard import, which is to republish an internal
interface as part of a public API (for example, overwriting a pure
Python implementation of an interface with the definitions from an
optional accelerator module and exactly which definitions will be
overwritten isn't known in advance).
See http://legacy.python.org/dev/peps/pep-0008/#imports

Maximize button does not work using Tkinter in RHEL5

I created a minimal Tkinter GUI as follows:
import Tkinter
root = Tkinter.Tk()
root.mainloop()
Everything is fine if I run the above code on RHEL5, except that the maximize button does not work properly(resizing is available). If I click the button, the window does not expand to occupy the whole screen. And I belive this issue is platform-specific, because there is no such issue for the same code on Windows.
Does anyone know the reason for this? Is there any solution? Thanks!
It works for me in Fluxbox. Try putting something in root like a label so it has something to display. Probably won't make any difference but worth a try.

Categories

Resources