Python 3 Tkinter - Messagebox with a toplevel as master? - python-3.x

I've found that when a toplevel widget calls a messagebox dialog (like "showinfo"), the root window is showed up, over the toplevel. Is there a way to set the Toplevel window as the master of the messagebox dialog ?
Here is a script to reproduce this :
# -*- coding:utf-8 -*-
# PYTHON 3 ONLY
from tkinter import *
from tkinter import messagebox
root = Tk()
root.title('ROOT WINDOW')
Label(root, text = 'Place the toplevel window over the root window\nThen, push the button and you will see that the root window is again over the toplevel').grid()
topWindow = Toplevel(root)
topWindow.title('TOPLEVEL WINDOW')
Label(topWindow, text = 'This button will open a messagebox but will\ndo a "focus_force()" thing on the root window').grid()
Button(topWindow, text = '[Push me !]', command = lambda: messagebox.showinfo('foo', 'bar!')).grid()
# --
root.mainloop()

You can set the parent argument to topWindow for the showInfo command:
Button(..., command=lambda: messagebox.showInfo(parent=topWindow, ...))
See also:
http://effbot.org/tkinterbook/tkinter-standard-dialogs.htm

This may address more current versions.
#TEST AREA forcommands/methods/options/attributes
#standard set up header code 2
from tkinter import *
from tkinter import messagebox
root = Tk()
root.attributes('-fullscreen', True)
root.configure(background='white')
scrW = root.winfo_screenwidth()
scrH = root.winfo_screenheight()
workwindow = str(1024) + "x" + str(768)+ "+" +str(int((scrW-1024)/2)) + "+" +str(int((scrH-768)/2))
top1 = Toplevel(root, bg="light blue")
top1.geometry(workwindow)
top1.title("Top 1 - Workwindow")
top1.attributes("-topmost", 1) # make sure top1 is on top to start
root.update() # but don't leave it locked in place
top1.attributes("-topmost", 0) # in case you use lower or lift
#exit button - note: uses grid
b3=Button(root, text="Egress", command=root.destroy)
b3.grid(row=0,column=0,ipadx=10, ipady=10, pady=5, padx=5, sticky = W+N)
#____________________________
root.withdraw()
mb1=messagebox.askquestion(top1, "Pay attention: \nThis is the message?")
messagebox.showinfo("Say Hello", "Hello World")
root.deiconify()
top1.lift(aboveThis=None)
#____________________________
root.mainloop()

Button(..., command=lambda: messagebox.showinfo("The Title", "A piece of text", parent=topWindow))
This will definitely work. The syntax of the messagebox is
messagebox.Function_Name(title, message [, options])
setting the parent argument is one of the options

add topWindow.attributes("-topmost", 1)
after defining the Toplevel, and this should fix the problem

Related

Python: TypeError: 'Label' object is not callable

from PIL import Image, ImageTk
from tkinter import *
from tkinter import Label
def open_window():
menu = Toplevel(root)
menu.geometry("800x800")
menu.title("my game's menu")
menu.resizable(False, False)
menu.geometry("800x800")
lbl = Label(menu, text ="Hello!").pack
menu.mainloop()
root = Tk()
root.geometry("400x300")
Label = Label(root, text="Are you ready?")
Label.pack()
root.title("quick question")
btn = Button(root, text="Yes", command= open_window)
btn.pack(padx=20, pady = 20)
root.mainloop()
I got this error while I was working on previously seen code: File "C:\Users\User\Desktop\naujas zaidimas\scratch.py", line 11, in open_window
lbl = Label(menu, text ="Hello!").pack
TypeError: 'Label' object is not callable
Does anyone know why/how to fix it?
The code has a number of fairly obvious errors and one insidious error
This import plays no role in current code
from PIL import Image, ImageTk
Not a good or preferred way to import tkinter
This will cause problems later on
from tkinter import *
This is unnecessary with the current inport method
from tkinter import Label
def open_window():
The rule for Python functions is: Names created in functions stay in functions.
It will require a global instruction to make 'menu' available elsewhere in your code
menu = Toplevel(root)
menu.geometry("800x800")
menu.title("my game's menu")
menu.resizable(False, False)
Duplicated geometry instruction
menu.geometry("800x800")
This object has already been defined as a Label object so trying to name it throws a TypeError
lbl = Label(menu, text ="Hello!").pack()
This is unnecessary since root.mainloop() has already been executed
menu.mainloop()
root = Tk()
root.geometry("400x300")
Here is another naming problem caused by the import method chosen
Label = Label(root, text="Are you ready?")
Label.pack()
root.title("quick question")
This button will enable you to create MANY Toplevel windows
The problem is, ALL of them will be called 'menu'!?
This is the insidious error
btn = Button(root, text="Yes", command= open_window)
btn.pack(padx=20, pady = 20)
root.mainloop()
# This solution avoids all the previous problems
import tkinter as tk
root = tk.Tk()
root.title("quick question")
root.geometry("400x300")
tk.Label(root, text = "Are you ready?").pack()
# This will give tkinter time to process the given instructions.
root.update()
menu = tk.Toplevel(root)
# withdraw will make menu temporarily invisible
menu.withdraw()
menu.title("my game's menu")
menu.geometry("800x800")
menu.resizable(False, False)
tk.Label(menu, text = "Hello!").pack()
# command will now make menu window visible
btn = tk.Button(root, text = "Yes", command = menu.deiconify)
btn.pack(padx = 20, pady = 20)
root.mainloop()
from PIL import Image, ImageTk
from tkinter import *
def open_window():
menu = Toplevel(root)
menu.geometry("800x800")
menu.title("my game's menu")
menu.resizable(False, False)
menu.geometry("800x800")
lbl = Label(menu, text ="Hello!").pack()
menu.mainloop()
root = Tk()
root.geometry("400x300")
lbl1 = Label(root, text="Are you ready?").pack()
root.title("quick question")
btn = Button(root, text="Yes", command= open_window)
btn.pack(padx=20, pady = 20)
root.mainloop()
I Played around both our codes and now somewhy it works.

How to show tkinter buttons in mac touch bar

I have a tkinter application and want to display some of its buttons in the Mac Touch Bar.
For Example
from tkinter import *
root = Tk()
send_button = Button(text = "Send",bg = 'sky blue',fg = 'black',font = "size 15",pady = 5)
send_button.grid()
root.mainloop()
So I want to integrate the send_button to show up in the Touch Bar, so is there a way to do that in tkinter.
There is a Package called PyTouchBar. I think this would help. https://github.com/Maxmad68/PyTouchBar/wiki
As an Example:
root = Tk()
PyTouchBar.prepare_tk_windows(root)
def function(button):
print('Button clicked!')
button = PyTouchBar.TouchBarItems.Button(title='Click me!', action=function)
PyTouchBar.set_touchbar([button])
root.mainloop()

Tkinter Toplevel window not appearing

Python 3.8, Win 10 is the os, Toplevel widget does not appear to be working with new window not appearing. Any guidance would be appreciated, thanks!
from tkinter import *
root = Tk()
def popup():
top = Toplevel(root)
my_label_top = Label(top, text="This is a Tkinter Popup")
top.mainloop()
my_button = Button(root, text="Popup, click here", command="popup")
my_button.grid(row=0, column=0)
root.mainloop()
Problem:
The only issue here is that the callback command shouldn't be a string.
Solution:
Remove the quotes around popup and the Toplevel window should appear.
Fixed Code:
from tkinter import *
root = Tk()
def popup():
top = Toplevel(root)
my_label_top = Label(top, text="This is a Tkinter Popup")
my_label_top.pack()
my_button = Button(root, text="Popup, click here", command=popup)
my_button.grid(row=0, column=0)
root.mainloop()
Tips:
Using top.mainloop() is not necessary.
You also forgot to pack() the Label(my_label_top)

How to get input from a function in Python and print in tkinter GUI?

from tkinter import *
def printSomething():
inputValue=textBox.get("1.0","end-1c")
res=response(inputValue)
label = Label(root, text=res)
#this creates a new label to the GUI
label.pack()
root = Tk()
button = Button(root, text="Print Me", command=printSomething)
button.pack()
textBox=Text(root, height=2, width=10)
textBox.pack()
root.mainloop()
I have written a python code that returns text. and print that in tkinter label.while i try to execute it shows "None" in label.
It would probably be better to create the label in the global namespace once and then just update the label every time you press the button.
I also recommend using import tkinter as tk vs from tkinter import * as it provides better maintainability as your code grows and you do not end up overwriting built in methods.
I have updated your code and changed a few things to better fit the PEP8 standard.
import tkinter as tk
def print_something():
label.config(text=text_box.get("1.0", "end-1c"))
root = tk.Tk()
tk.Button(root, text="Print Me", command=print_something).pack()
text_box = tk.Text(root, height=2, width=10)
text_box.pack()
label = tk.Label(root)
label.pack()
root.mainloop()
Just changing your line:
res = response(inputValue)
to
res = inputValue
worked for me, creating a new label every time I pressed the button.

Python 3 Radio button controlling label text

I am in the process of learning Python3 and more of a necessity, the TkInter GUI side. I was working my way through a book by James Kelly, when I encountered this problem. All his examples made a new window with just label/canvas/check box etc which seemed to work OK.
But as I wanted to experiment in a more real world scenario I put most things on one window. This where I encountered my problem. I can not get the radio button in the frame to alter the wording of a label in the parent window.
Complete code is:-
#! /usr/bin/python3
from tkinter import *
def win_pos(WL,WH,xo=0,yo=0) :
# Screen size & position procedure
# Screen size
SW = home.winfo_screenwidth()
SH = home.winfo_screenheight()
# 1/2 screen size
sw=SW/2
sh=SH/2
# 1/2 window size
wl=WL/2
wh=WH/2
# Window position
WPx=sw-wl+xo
WPy=sh-wh+yo
# Resulting string
screen_geometry=str(WL) + "x" + str(WH) + "+" + str(int(WPx)) + "+" \ + str(int(WPy))
return screen_geometry
# Create a window
home=Tk()
home.title("Radio buttons test")
# Set the main window
home.geometry(win_pos(600,150))
lab1=Label(home)
lab1.grid(row=1,column=1)
fraym1=LabelFrame(home, bd=5, bg="red",relief=SUNKEN, text="Label frame text")
fraym1.grid(row=2,column=2)
laybl1=Label(fraym1, text="This is laybl1")
laybl1.grid(row=0, column=3)
var1=IntVar()
R1=Radiobutton(fraym1, text="Apple", variable=var1, value=1)
R1.grid(row=1, column=1)
R2=Radiobutton(fraym1, text="Asus", variable=var1, value=2)
R2.grid(row=1, column=2)
R3=Radiobutton(fraym1, text="HP", variable=var1, value=3)
R3.grid(row=1, column=3)
R4=Radiobutton(fraym1, text="Lenovo", variable=var1, value=4)
R4.grid(row=1, column=4)
R5=Radiobutton(fraym1, text="Toshiba", variable=var1, value=5)
R5.grid(row=1, column=5)
# Create function used later
def sel(var) :
selection="Manufacturer: "
if var.get() > 0 :
selection=selection + str(var.get())
lab1.config(text=selection)
R1.config(command=sel(var1))
R2.config(command=sel(var1))
R3.config(command=sel(var1))
R4.config(command=sel(var1))
R5.config(command=sel(var1))
R1.select()
mainloop()
I realise that there is room for improvement using classes/functions but I need to get this resolved in my head before I move on. As it can be hopefully seen, I'm not a complete novice to programming, but this is doing my head in.
Can a solution, and reasoning behind the solution, be given?
You can modify your label's text by assigning the same variable class object, var1 as its textvariable option as well but since lab1's text is slightly different, try removing:
R1.config(command=sel(var1))
R2.config(command=sel(var1))
R3.config(command=sel(var1))
R4.config(command=sel(var1))
R5.config(command=sel(var1))
R1.select()
and modify sel to:
def sel(*args) :
selection="Manufacturer: "
selection=selection + str(var1.get())
lab1.config(text=selection)
and then call var1.trace("w", sel) somewhere before mainloop as in:
...
var1.trace("w", sel)
mainloop()
Also for a simple example:
import tkinter as tk
root = tk.Tk()
manufacturers = ["man1", "man2", "man3", "man4", "man5"]
lbl = tk.Label(root, text="Please select a manufacturer.")
lbl.pack()
# create an empty dictionary to fill with Radiobutton widgets
man_select = dict()
# create a variable class to be manipulated by radiobuttons
man_var = tk.StringVar(value="type_default_value_here_if_wanted")
# fill radiobutton dictionary with keys from manufacturers list with Radiobutton
# values assigned to corresponding manufacturer name
for man in manufacturers:
man_select[man] = tk.Radiobutton(root, text=man, variable=man_var, value=man)
#display
man_select[man].pack()
def lbl_update(*args):
selection="Manufacturer: "
selection=selection + man_var.get()
lbl['text'] = selection
#run lbl_update function every time man_var's value changes
man_var.trace('w', lbl_update)
root.mainloop()
Example with label's identical to that of radiobutton's value:
import tkinter as tk
root = tk.Tk()
# radiobutton group will the button selected with the value=1
num = tk.IntVar(value=1)
lbl = tk.Label(root, textvariable=num)
zero = tk.Radiobutton(root, text="Zero", variable=num, value=0)
one = tk.Radiobutton(root, text="One", variable=num, value=1)
#display
lbl.pack()
zero.pack()
one.pack()
root.mainloop()

Resources