I have a doubt, how can I continue running the script without closing a messagebox from tkinter? Or show multiple messageboxes at the same time
An example:
from tkinter import messagebox as MB
aux = 0
def scrpt():
global aux
#the script stops here ⬇️
MB.showinfo(title="Simple Program", message="aux= "+str(aux))
#the code below isnt ejecuted if i didnt accept or close the above popup ⬆️
aux += 1
while True:
scrpt()
I want to know if there is a way to continue running the script without closing the tkinter messagebox popup.
I don't think that is possible with message box because I tried it with many ways but in vain, however …
you can do it by using Toplevel() class:
from tkinter import *
for i in range(0, 100):
a = Toplevel()
Label(a, text=str(i)).pack()
mainloop()
The problem is by closing one window all will close too, you can do this so it won't close together:
for i in range(0,100):
a= Tk()
mainloop()
Related
I am trying to write a program where i have removed the main window close options and providing a exit button to the user to close the program.
After pressing i need to do some processing in the background which would be time consuming, i don't want user to close the program while that is going on accidentally. Is there a way to remove all buttons from the messagebox which is presented ?
import tkinter as tk
from win32api import GetSystemMetrics
from tkinter import messagebox
def on_closing():
pass
def exit():
messagebox.showinfo("Wait", "Please wait for background process to complete")
root.destroy()
root = tk.Tk()
root.resizable(width=False, height=False)
root.protocol("WM_DELETE_WINDOW", on_closing)
width = GetSystemMetrics(0)
height = GetSystemMetrics(1)
root.geometry('{}x{}'.format(width,height))
exitButton = tk.Button(root,text="Exit",width=15,command=exit)
exitButton.grid(row=0,column=1,padx=6,pady=6)
root.overrideredirect(True)
root.mainloop()
In the Background : There are some files generated on user's machine and i would like to archive them using python library. The files can go maybe sometime at 1GB so i think it would take more amount of time, if the laptop on which it is run is having very less computing power. And this would be the case for my base hence i want them just to wait until that popup is closed. This i can define in user manual.
I am not sure what work you want to do, but for this example I'm doing a work of printing something and then sleeping and then printing it. So this takes about 20 seconds. And in those 20 seconds you wont be able to exit the GUI.
import tkinter as tk
from win32api import GetSystemMetrics
from tkinter import messagebox
import time
import threading
def on_closing():
if started == False: #if work is not going on, then quit
root.destroy()
else: # else show the message.
messagebox.showinfo("Wait", "Please wait for background process to complete")
def work():
global started
started = True #mentioning that the work started
print('Hey')
time.sleep(5)
print('There')
time.sleep(5)
print('Whats Up')
time.sleep(5)
print('Cool?')
time.sleep(5)
started = False #mentioning that the work stopped
started = False #initially work is not started
root = tk.Tk()
root.resizable(width=False, height=False)
root.protocol("WM_DELETE_WINDOW", on_closing)
width = GetSystemMetrics(0)
height = GetSystemMetrics(1)
root.geometry('{}x{}'.format(width,height))
exitButton = tk.Button(root,text="Exit",width=15,command=on_closing)
exitButton.grid(row=0,column=1,padx=6,pady=6)
Button = tk.Button(root,text="Work",width=15,command=threading.Thread(target=work).start)
Button.grid(row=1,column=1,padx=6,pady=6)
# root.overrideredirect(True)
root.mainloop()
Here, started acts like a flag. You have to set it to True before starting your work and set it to False after it ends.
You can ignore the fact that I created a new button and used threading, it was just to simulate to you an example of work done. Threading helps the GUI to not freeze. Though I'm not sure if this will work with root.overrideredirect(True), but I think you can get rid of it.
With this code I was able to create a TK Inter pop-up with a button to run a Sample_Function.
This Sample_Function destroys the tk pop-up, runs another python file, and then opens itself (the first pop-up) again.
How can I run the other_python_file and pop-up 'itself' at the same time — so I can be able to trigger many functions before each one gets completed?
import sys, os
from tkinter import *
import tkinter as tk
root = Tk()
def Sample_Function():
root.destroy()
sys.path.insert(0,'C:/Data')
import other_python_file
os.system('python this_tk_popup.py')
tk.Button(text='Run Sample_Function', command=Sample_Function).pack(fill=tk.X)
tk.mainloop()
I think this will do close to what you want. It uses subprocess.Popen() instead of os.system() to run the other script and rerun the pop-up which doesn't block execution while waiting for them to complete, so they can now execute concurrently.
I also added a Quit button to get out of the loop.
import subprocess
import sys
from tkinter import *
import tkinter as tk
root = Tk()
def sample_function():
command = f'"{sys.executable}" "other_python_file.py"'
subprocess.Popen(command) # Run other script - doesn't wait for it to finish.
root.quit() # Make mainloop() return.
tk.Button(text='Run sample_function', command=sample_function).pack(fill=tk.X)
tk.Button(text='Quit', command=lambda: sys.exit(0)).pack(fill=tk.X)
tk.mainloop()
print('mainloop() returned')
print('restarting this script')
command = f'"{sys.executable}" "{__file__}"'
subprocess.Popen(command)
My program streams data and I want to create a popup displaying some text whenever a condition is met. I tried to create a simple tkinter window and ctypes window, but both seem to block my code, preventing it from continuing until the window has been closed. How can I create simple popup window functionality in for example a loop?
What I have so far is something of this structure.
import tkinter as tk
for i in range(11):
if i%5 == 0: # Any condition
popup = tk.Tk()
label = ttk.Label(popup, text='hi', font=('Verdana', 12))
label.pack(side='top', padx=10, pady=10)
popup.mainloop()
and
import ctypes
for i in range(11):
if i%5 == 0: # Any condition
popup = ctypes.windll.user32.MessageBoxW
popup(None, 'hi', 'title', 0)
However, in both cases the loop will not proceed until I close the popup.
Case 1 - Tkinter:
You are using mainloop() which is no different than a true while loop. You can make it run continuously by removing it.
import tkinter as tk
from tkinter import ttk
for i in range(11):
if i%5 == 0: # Any condition
popup = tk.Tk()
label = ttk.Label(popup, text='hi', font=('Verdana', 12))
label.pack(side='top', padx=10, pady=10)
Case 2 - Ctypes:
To make it run continuously, you will have to use threading.
import ctypes, threading
for i in range(11):
if i%5 == 0: # Any condition
popup = ctypes.windll.user32.MessageBoxW
threading.Thread(target = lambda :popup(None, 'hi', 'title', 0)).start()
Not too familiar with ctypes, but for tkinter the UI will always be blocking your main code during the mainloop.
You can somewhat bypass it if you just instantiate your Tk() without invoking mainloop and use the after function:
import tkinter as tk
from tkinter.messagebox import showinfo
root = tk.Tk()
root.withdraw()
for i in range(10):
if i in (5, 8):
root.after(ms=1, func=lambda x=i: showinfo('Message!', f'Stopped at {x}'))
# ... do something here
The root.after queues the message box to be displayed after 1 millisecond (ms=1).
A better way might be to create a modeless message/dialog box in ctypes but as mentioned, I'm not too familiar and a quick search didn't yield any simple solution.
I am using python 3.
If I opan an error messagebox, i get two frames, one is emty and one is the error-window. That is my code:
from tkinter import messagebox
messagebox.showwarning('warning', 'warning')
Everything works correctly in your example. The empty window is the main window of Tk. It is always open when you start any Tk program. You can minimize it if you want, but closing it terminates the main loop.
Try this:
root = tkinter.Tk()
root.withdraw()
messagebox.showwarning('warning', 'warning')
Thank you DYZ,
in my code is no main window, (eg.: main = Tk() ... main.mainloop), because of that the warning massage create one. I could solve the problem by create one and minimize it. at the end of massagebox I destroyed it to continue in code.
from tkinter import *
from tkinter import messagebox
main = Tk()
main.geometry("500x400+300+300")
def message():
main.geometry("0x0")
messagebox.showwarning("Say Hello", "Hello World")
main.destroy()
B1 = Button(main, text = "Start Dialog",fg="dark green", command = message)
B1.pack()
main.mainloop()
print("finish dialog")
I'm using jupyter notebook on mac, recently I need to write interactive dialog box, so after google, I use Tkinter to make an interactive window.
But I was bothered by this problem couples day ,and still can't find a solution way.
Fisrt example:
from Tkinter import *
from tkFileDialog import askopenfilename
import sys
import os,time
def callback():
name= askopenfilename()
print name
errmsg = 'Error!'
Button(text='File Open', command=callback).pack(fill=X)
mainloop()
Second example:
from Tkinter import *
import sys,os
class YourApp(Tk):
def quit_and_close(self):
app.quit()
#os._exit(0)
#sys.exit(1)
#exit(0)
app = YourApp()
app.title('example')
app.geometry('400x300+200+200')
b = Button(app, text = "quit", command = app.quit_and_close)
b.pack()
app.mainloop()
And the third one:
import Tkinter as tk
import tkMessageBox
def ask_quit():
if tkMessageBox.askokcancel("Quit", "You want to quit now? *sniff*"):
root.destroy()
root = tk.Tk()
root.protocol("WM_DELETE_WINDOW", ask_quit)
root.mainloop()
After running those above code, always need have to force quit python launcher.
It is very weird, and annoying because after forcing quit, I will got the error:
Is it necessary to use python launcher as default window?
Is there possible to set another window to open ?
or is there proper way to close the launcher without causing programming crash?
p.s Even I try to use wxpython, it still open python launcher and got the same problem.