I have a simple program as follows:
from Tkinter import *
class Run:
def __init__(self,parent):
parent.overrideredirect(True)
root = Tk()
app = Run(root)
root.mainloop()
When I run this program, the undecorated root window always stays on top.
How can I make it so any other window can be on top of it, whilst having no decorations?
I have tried setting 'topmost' to 'False' as well, but to no avail.
I am running Ubuntu 13.04.
Thanks in advance
This code below, will put your window on the background on every 100ms, no matter what, so everything will be in the front of it all the time. I think this is what you were asking for:
from tkinter import *
class Run:
def __init__(self):
self.root = Tk()
self.root.overrideredirect(True)
def put_back(self):
# this method will put the window to the background
self.root.lower()
# recursive calling of put_back method
self.root.after(100, self.put_back)
app = Run()
# Start the recursion
app.put_back()
app.root.mainloop()
Seems like this should happen automatically if I click a different window.
Related
I have created a class "Node" which creates a binary tree. (I know i can use binarytree module but its a project given to me in DSA subject.)
class Node:
def __init__(self, data) -> None:
#initialisation
def addNode(self, data):
# Code to add data.
def traverse(self):
#traverses the tree and returns a dict
def view(
self,
length=500,
width=1000,
yDist=50,
xDistScale=0.25,
title='Tree View',
):
# shows the tree in a tkinter window as in the screenshot attached
tree = self.traverse()
root = tk.Tk()
self.root=root
root.geometry(str(width)+'x'+str(length))
root.title(title)
# ........ some code which places the nodes on the window using the place() method
root.mainloop()
Now, I import the code in an another file, create an instance of the class add some nodes and call the view() method it works fine but the code after the view() methd does not run till I close the tkinter window.
How can I make the code after view() run without the window being closed?
Its ok if the window is not able to update.
Code where I import and use the node class :
t1 = Node(15)
t1.addNode(12)
t1.addNode(27)
t1.addNode(7)
t1.addNode(14)
t1.addNode(20)
t1.addNode(88)
t1.addNode(23)
t1.view()
# The code here does not run until I close the window.
Output of the above code :
Link to image
I tried googling and also viewed following stackoverflow posts:
Calling a tkinter application from a different class in python,
A code needs to be continued...(Python with Tkinter)
How would I continue to run code after importing a Tkinter file?
Few other websites and guides...
But nothing was helpful.
Please help/guide me.
I am new to StackOverflow and Python.
Thanks in Advance :)
Method 1: Don't update window
You could replace the root.mainloop() with root.update(). This will stop showing any changes to the window. The window will only and always close if the program stops running.
Method 2: using threading
You could useimport threading to run t1.view() in another thread: threading.Thread(target=t1.view).start(). This may result in a Tcl_AsyncDelete error.
I have a very simple python code: a tkitner button that process some images in the background. I wanted to open a tkinter toplevel to show the user that it was doing something, but for my surprise is not working as I thought it would. The command on the tk.Button is the next method:
def processing(self):
"""Starts the images processing"""
# Open a Tk.Toplevel
aux_topLevel = Splash(self.window) # a simple Tk.Toplevel class, that works perfectly
self._process_images() # starts processing the images
# I wanted to kill here the topLevel created before
aux_topLevel.destroy()
My surprise: the window is displayed once the processing images is done (tried it out adding prints and time.sleep), however, i couldn't display the TopLevel when I wanted to.
Is there anything am I doing wrong? Any help is appreciated. Thank you.
Consider the following example and try to run it.
What you'd think should happen is that the new Toplevel window should open, some event happens for a period of time and then the window is destroyed.
What actually happens is the window is opened, but never displayed, the task occurs and then the window is destroyed.
from tkinter import *
import time
def processing():
new = Toplevel(root)
new.geometry("200x150")
lbl = Label(new,text="--")
lbl.grid()
for i in range(50):
time.sleep(0.1)
#Un-comment the line below to fix
#root.update()
print(i)
lbl['text'] = "{}".format(i)
new.destroy()
root = Tk()
root.geometry('200x100')
btnGo = Button(root,text="Go",command=processing)
btnGo.grid()
root.mainloop()
If you un-comment out the root.update() line and re-run the code, the window will be displayed.
There are better ways to deal with tasks that takes a while to process, such as threading.
I have a windows application with a python API (supports python 3). You can provide a class that has a main function. On program startup, an instance of this class is created, and the main function is called periodically. I can configure the frequency, but nothing else. (I cannot change the way the API works)
Now, I'd like to use tkinter for some visualizations, charts, and so on. Here is an example of my current class structure:
import tkinter as tk
class Script:
def __init__(self):
self.root = tk.Tk()
self.count = 0
def main(self):
# do some stuff
print(str(self.count))
self.count += 1
# update gui
self.root.update()
# This is to simulate the software behavior.
import time
scriptInstance = Script()
for i in range(0, 20 * 10):
scriptInstance.main()
time.sleep(0.1)
The main issue I have is, that the root.update() method freezes the main-function as long as you interact with Tkinter. You can see that with the example above, that the number is not counting up as long as you are moving the window. Is there a way to prevent that?
I tried to call the root.update() form another thread, which did not work because Tkinter does not allow that.
Thank you for any help.
Here is a sample situation:
I have written a tk GUI that opens and edits e.g. .txt files. I'm currently on a mac, but I might also want to run this on windows. Currently the main Application class creates its own internal tk.Tk() like so
import tkinter as tk
class App:
def __init__(self):
self.root = tk.Tk()
tk.Label(master=self.root,text="content").pack()
if __name__ == '__main__':
a=App()
a.root.mainloop()
I want to add multi file capabilities to the application. In the current system this would result in 2 tk.Tk() instances running which I couldn't get to work and people say is unpredictable.
I want to be able to close any of the multiple files and still have the application running until the last window is closed and then the application quit or stays without a window (like on a mac).
My problem is that if I use tk.Toplevel() for each of my windows I have a ugly default tk.Tk() window which I would need to hide which seams inelegant. It would also be messy to determine which file is currently in focus for actions with the menubar.
I'm also considering each file being it's own application instance like on Windows, but that would fill the dock with repeated icons and be inconsistent with the rest of the system.
Here are the possible way I came up with:
Multiple Tks (Works but more complex examples are unpredictable):
import tkinter as tk
class App:
def __init__(self):
self.root = tk.Tk()
tk.Label(master=self.root,text="content").pack()
tk.Button(master=self.root,text="new_window",command=self.open).pack()
def open(self):
App()
if __name__ == '__main__':
a=App()
a.root.mainloop()
Hidden tk window and multiple Toplevels (Needs hiding the Tk and the osx menubar commands like view->change_colors would need to manaly decide where to direct comands):
import tkinter as tk
class App:
def __init__(self):
self.root = tk.Toplevel()
tk.Label(master=self.root,text="content").pack()
tk.Button(master=self.root,text="new_window",command=self.open).pack()
def open(self):
App()
if __name__ == '__main__':
tk.Tk()
a=App()
a.root.mainloop()
Each Window is its own Application and fully independant (Dosn't fit in with the other mac applications, the implementation is ugly):
#!/usr/local/bin/python3
import tkinter as tk
import sys,os
class App:
def __init__(self):
self.root = tk.Tk()
tk.Label(master=self.root,text="content").pack()
tk.Button(master=self.root,text="new_window",command=self.open).pack()
def open(self):
os.system(sys.argv[0]+"&")
if __name__ == '__main__':
a=App()
a.root.mainloop()
I was alos think of maybe doing it with threads but I think I must be over thinking it so I came here.
Is there a generally accepted way of doing this in tk?
The generally accepted way is just like you describe: use Toplevel for additional windows, and hide the root window if you don't want to see it.
Another choice is to make your main program a non-GYI app, and each window is created by spawning a new process.
Hidden tk window and multyple Toplevels (Needs hiding the Tk and the osx menubar commands like view->change_colors would need to manaly decide where to direct comands):
It is easy to get into "which goes with what" hell with multiple Toplevels. Instead create a separate class for each new Toplevel with built in responses to button clicks, etc. Pass "root" to the class and let it create, update, and destroy as necessary, and keep track of it's own variables. If you want to use variables elsewhere, then store the class instance when the Toplevel classes are called and create the variables within the class as instance attributes.
I am building an Interface with TKinter and I have the problem, that whenever create a new window the standardized tkinter window of 200x200 pixel with nothing in it flashes up for a fraction of a second and AFTER that all my modifications (widgets ect.) are made. This happens before AND after calling the mainloop.
The Main-Interface is created.
Mainloop stats
Flashing window
Main-Interface appears
Also after Mainloop was called this happens with newly created windows.
Main-Interface appears--> Push a button, that creates a new window
Flashing window
new window appears
Sadly I cannot give you a sample code... If I try to do a minimal example, this doesn't happen. Maybe the standard window is created, but it is changed so fast, that it doesn't appear on screen. I don't even know what to look up in this case... searching "tkinter flashing window" yields nothing.
EDIT: I found the source of the problem. It seems to be caused by wm_iconbitmap, FigureCanvasTkAgg and tkinter.Toplevel. If you remove the the icon out of the code, it works fine, no flashing. But if I use it together with one of the other, the window flashes when created. Try it out with the code below. You have to put the icon in the working directory of course.
Here is a code sample and the link to the icon I am using, but I suppose any icon will do.
# coding=utf-8
import numpy as np
import matplotlib as mpl
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import tkinter as tk
import os
class INTERFACE(object):
def __init__(self):
self.root = tk.Tk()
self.root.protocol("WM_DELETE_WINDOW", self.EXIT)
self.root.wm_iconbitmap( os.path.abspath("icon.ico")) #<---- !!!!!!
self.root.geometry("1024x768")
canvas = FigureCanvasTkAgg(self.testfigure(), master=self.root) #<---- !!!!!!
canvas.get_tk_widget().grid(sticky=tk.N+tk.W+tk.E+tk.S)
self.root.rowconfigure(0, weight=1)
self.root.columnconfigure(0, weight=1)
def testfigure(self):
x=np.linspace(0, 2*np.pi,100)
y=np.sin(x)
fig = mpl.figure.Figure()
sub = fig.add_subplot(111)
sub.plot(x,y)
return fig
def EXIT(self):
Top = tk.Toplevel(master=self.root)
Top.wm_iconbitmap( os.path.abspath("icon.ico")) #<---- !!!!!!
Top.transient(self.root)
Top.resizable(width=False, height=False)
Top.title("Exit")
tk.Message(Top,text="Do you really want to quit?", justify=tk.CENTER, width=300).grid(row=0,columnspan=3)
tk.Button(Top,text="YES",command=self.root.destroy).grid(row=1,column=0)
tk.Button(Top,text="No",command=self.root.destroy).grid(row=1,column=1)
tk.Button(Top,text="Maybe",command=self.root.destroy).grid(row=1,column=2)
def start(self):
self.root.mainloop()
if __name__ == '__main__':
INTERFACE().start()
I know this is an old question, but I've experienced a similar situation and have found a solution.
In my case, I've isolated the issue to the use of iconbitmap. I've managed to solve it by calling iconbitmap with the after method just before calling root.mainloop().
Example:
from tkinter import *
root = Tk()
w = Label(root, text="Hello, world!")
w.pack()
root.geometry('300x300+500+500')
root.after(50, root.iconbitmap('icon.ico'))
root.mainloop()
This method has worked on Toplevel() windows with icons as well.
Tested on Win 8.1 with Python 3.5.0.
Edit: Upon further inspection I've noticed that the behavior changes relative to root.geometry's presence as well. My initial example didn't have it and I only noticed after a few tries that it still had the same issue. The time delay in the after method doesn't seem to change anything.
Moving root.geometry below the after method yields the same issue for some reason.
Most likely, somewhere in your initialization code you're calling update or update_idletasks, which causes the current state of the GUI to be drawn on the screen.
Another possible source of the problem is if you're creating multiple instances of Tk rather than Toplevel.
Without seeing your code, though, all we can do is guess.
Your best route to solving this problem is to create a small example that has the same behavior. Not because we need it to help you, but because the effort you put into recreating the bug will likely teach you what is causing the bug.
This should work but it requires win32gui
import win32gui
def FlashMyWindow(title):
ID = win32gui.FindWindow(None, title)
win32gui.FlashWindow(ID,True)