tkinter wait_variable doesn't return - python

i've a tkinter toplevel widget were you can type some text, and then press ok. it is created in a function: if you call that funtion the program should wait for a click on the button and than the function should return that text, so that my function have the same use a the input function in python 3. now my problem is: how can i pause my script until the user clicked on a button, so that all other files in my project pause (there happens nothing if the user clicks on a button in another tkinter window) are paused? i tried to use button.wait_variable(chosen) and when the user clicks on the button the variable "chosen" will change.
def choosefile():
root = tk.Tk()
root.geometry("275x50")
chosen = tk.BooleanVar()
chosen.set(False)
label = tk.Label(root, text="enter name of file (without extention)")
label.pack(fill="both")
entry = tk.Entry(root)
entry.pack(side="left", expand=True, fill="x")
button = tk.Button(root, text="Ok", command=lambda: [chosen.set(True), output(chosen.get())])
button.pack(side="right")
output("waiting")
button.wait_variable(chosen)
output("not waiting")
result = entry.get() + ".py"
root.quit()
return result
this works ok if you only run this file, but when i this run with main.py(below) the window don't destroy and also not return.
main.py
from tkinter import Tk, Button, Entry, StringVar
import tkinter.font as tkfont
from customtext import CustomText
from execute import Execute
from coloring import color
from files import create, openfile, choosefile
from alert import alert
import keyboard
class App(Tk):
def __init__(self):
super(App, self).__init__()
self.width = self.winfo_screenwidth() - 1
self.height = self.winfo_screenheight() - 1
self.attributes('-fullscreen', True)
self.state = StringVar()
self.state.set("saved")
self.input = CustomText(self)
self.input.place(x=10, y=10, width=self.width - 20, height=self.height - 20)
self.input.bind("<<TextModified>>", lambda a: [color(self.input), self.state.set("unsaved")])
self.run = Button(self, text="run", command=lambda: [create(self.name.get("1.0", "end-1c"), ".py", self.input.get("1.0", "end-1c")), Execute(self.name.get("1.0", "end-1c")), self.state.set("saved")])
self.run.place(x=self.width - 70, y=20, width=50, height=30)
self.exit = Button(self, text="exit", command=lambda: self.destroy())
self.exit.place(x=self.width - 130, y=20, width=50, height=30)
self.save = Button(self, text="save", command=lambda: [create(self.name.get("1.0", "end-1c"), ".py", self.input.get("1.0", "end-1c")), self.state.set("saved")])
self.save.place(x=self.width - 190, y=20, width=50, height=30)
self.open = Button(self, text="open", command=lambda: self.openfile())
self.open.place(x=self.width - 250, y=20, width=50, height=30)
self.name = CustomText(self, border=3, font=('Arial', 13))
self.name.place(x=self.width - 360, y=21, width=100, height=30)
def openfile(self):
if self.state.get() == "unsaved":
choise = alert("your code is unsaved, save now?")
if choise == "Ok":
create(self.name.get("1.0", "end-1c"), ".py", self.input.get("1.0", "end-1c"))
self.state.set("saved")
self.input.delete("1.0", "end")
self.input.insert("end-1c", openfile(choosefile())) # here choosefile is called.
if __name__ == "__main__":
app = App()
keyboard.add_hotkey("ctrl+enter", lambda: [keyboard.write("\b"), Execute(app.input.get("1.0", "end"))])
app.mainloop()
can someone help? thanks in advance!
EDIT:
i tried to implemant what acw1668 commented and it works! what i've done: in all my functions, i added a parameter master, so that i at any place in my project can use tk.Toplevel(master). now, since i only one instance of tk.Tk() have, it is working correctly.

Related

How to change focus of simpledialog in Tkinter?

I have several simpledialog popup windows. The first one that shows is in focus and after it closes then every single one after that is not in focus. The simpledialog code is this:
from tkinter import *
from tkinter import messagebox
import os
import tkinter as tk
from tkinter import simpledialog
def doing_stocks():
name = myaskstring("Input data", "Enter box number:", parent = root)
name2 = myaskstring("Input data2", "Enter box number2:", parent = root)
name3 = myaskstring("Input data3", "Enter box number3:", parent = root)
class My_QueryString(tk.simpledialog._QueryString):
def body(self, master):
self.bind('<KP_Enter>', self.ok)
self.bind('<Return>', self.ok)
w = Label(master, text=self.prompt, justify=LEFT)
w.grid(row=0, padx=5, sticky=W)
self.entry = Entry(master, name="entry")
self.entry.grid(row=1, padx=5, sticky=W+E)
if self.initialvalue is not None:
self.entry.insert(0, self.initialvalue)
self.entry.select_range(0, END)
root.update_idletasks()
self.entry.focus_force()
return self.entry
def myaskstring(title, prompt, **kw):
d = My_QueryString(title, prompt, **kw)
root.update_idletasks()
answer = d.result
d.destroy()
return answer
root = Tk()
root.geometry("700x761")
label1 = Label(root, text="")
label1.place(x = 0, y = 0)
button2 = Button(root, text = "Doing Stocks", command=doing_stocks).place(x = 300, y = 340)
root.mainloop()
This is a simplified version of the code. I call my simpledialog popups like this:
myaskstring("Title", "Prompt", parent = root)
In the doing_stocks() method the first time I call myaskstring the window and the entry field will be in focus then all times after that it won't be. How can I make every simpledialog be in focus when it appears on the screen?
I agree is seems odd that the focus isn't set to each My_QueryString instance when it's initialized. Regardless of the reason why, a workaround for it not happening is to bind a <Map> event handler function to the dialog's Entry widget to shift keyboard focus to itself whenever it's made visible.
The code below shows an implementation doing that. It's based on your code with the important changes indicated with # ALL CAP comments to make them stand out.
import tkinter as tk
from tkinter import simpledialog
from tkinter.constants import *
def doing_stocks():
name = myaskstring("Input data", "Enter box number:", parent=root)
name2 = myaskstring("Input data2", "Enter box number2:", parent=root)
name3 = myaskstring("Input data3", "Enter box number3:", parent=root)
class My_QueryString(tk.simpledialog._QueryString):
def body(self, master):
self.bind('<KP_Enter>', self.ok)
self.bind('<Return>', self.ok)
w = tk.Label(master, text=self.prompt, justify=LEFT)
w.grid(row=0, padx=5, sticky=W)
self.entry = tk.Entry(master, name="entry")
self.entry.grid(row=1, padx=5, sticky=W+E)
self.entry.bind('<Map>', self.on_map) # <--- ADDED.
if self.initialvalue is not None:
self.entry.insert(0, self.initialvalue)
self.entry.select_range(0, END)
root.update_idletasks()
# self.entry.focus_force() # <--- NOT NEEDED.
return self.entry
# ADDED METHOD.
def on_map(self, event):
self.entry.focus_force()
def myaskstring(title, prompt, **kw):
d = My_QueryString(title, prompt, **kw)
root.update_idletasks()
answer = d.result
# d.destroy() # <--- NOT NEEDED.
return answer
root = tk.Tk()
root.geometry("700x761")
label1 = tk.Label(root, text="")
label1.place(x = 0, y = 0)
button2 = tk.Button(root, text = "Doing Stocks", command=doing_stocks)
button2.place(x = 300, y = 340)
root.mainloop()

How can I exicute my previous code( how to go back in the window.)

In this code I'am trying to execute my two different code in same window or it seems like it is executing in same window.
When I'm clicking on "next_button" is execute the function "next_screen". Here we have again a button by which I'm trying to execute my previous (main_screen) code but it's not working.
If my logic of trying to execute two codes in same screen is wrong. Then please let me know and then how can I execute two or more files code in same root(screen or window).
import tkinter as md
def next_screen():
frame.destroy()
root.geometry("300x200")
def main_screen():
next_frame.destroy()
root.resizable(width = False, height = False)
root.geometry("200x200")
next_frame = md.Frame(root)
next_frame.pack()
label = md.Label(next_frame, text = "Click bellow button to go to main window", pady = 20)
label.pack()
button = md.Button(next_frame, text = "Clikc Me", font = "verdana 15", command = main_screen)
button.pack()
root = md.Tk()
root.geometry("200x200")
frame = md.Frame(root)
frame.pack()
label = md.Label(frame, text ="Main window", pady = 20)
label.pack()
next_button = md.Button(frame, text ="Go Forward", font = "verdana 15", command = next_screen)
next_button.pack()
root.mainloop()
With this code I'm able to go in forward direction but cannot come back. Maybe it will use loop to execute.
It becomes much easier if you use a class for something like this. Here is a quick example I made:
import tkinter as md
class Screens:
def __init__(self):
self.frame = None
self.main_screen()
def main_screen(self):
if self.frame is not None:
self.frame.destroy()
frame = md.Frame(root)
frame.pack()
label = md.Label(frame, text="Main window", pady=20)
label.pack()
next_button = md.Button(frame, text="Go Forward", font="verdana 15", command=self.next_screen)
next_button.pack()
self.frame = frame
def next_screen(self):
self.frame.destroy()
next_frame = md.Frame(root)
next_frame.pack()
label = md.Label(next_frame, text="Click bellow button to go to main window", pady=20)
label.pack()
button = md.Button(next_frame, text="Clikc Me", font="verdana 15", command=self.main_screen)
button.pack()
self.frame = next_frame
root = md.Tk()
root.geometry("200x200")
screen = Screens()
root.mainloop()
Make sure to modify it to suit your needs.

This my small python program .when button clicks new window opening. how it is possible to in one window only

This is small Python button program. My problem was when I am clicking button always opening new window. I want one window execution.
from tkinter import *
import sys
def pressed():
root = Tk()
root.title('My Window2')
root.geometry('200x200')
button = Button(root,text = 'press2',command = pressed2)
button.pack(pady = 20, padx = 20)
def close():
quit()
def pressed1():
print('second window')
def pressed2():
root = Tk()
root.title('My Window3')
root.geometry('200x200')
button = Button(root,text = 'press3',command = pressed1)
button.pack(pady = 20, padx = 20)
button = Button(root,text = 'back',command = pressed)
button.pack(pady = 20, padx = 20)
root = Tk()
root.title('My Window')
root.geometry('200x200')
button = Button(root,text = 'press',command = pressed)
button2 = Button(root,text = 'Exit',command = close)
button.pack(pady = 20, padx = 20)
button2.pack(pady = 20, padx = 20)
mainloop()
I have not used Tkinter, but here is what looks like is happening.
1. on my win 7 python 2.6 it is Tkinter, not tkinter
2. when you use root = Tk() it is creating a new window; if you remove the root = Tk() from pressed() and pressed2() it uses the original window over again.
It's not clear what you want, but if you are trying to modify the text, and command associated with the button then you just need to configure those attributes.
Something like this should work. It can be modified to add new buttons instead of reusing the same button. I made the class inherit from Frame, but you could also choose to inherit from Tk. (Note: This is Python 3 code)
import tkinter
class ButtonPressWindow(tkinter.Frame):
def __init__(self, master):
tkinter.Frame.__init__(self, master)
master.title('My Window')
master.geometry('200x200')
self.button1 = tkinter.Button(self, text='press', command=self.pressed)
self.button2 = tkinter.Button(self, text='Exit', command=self.close)
self.button1.pack(pady=20, padx=20)
self.button2.pack(pady=20, padx=20)
def pressed(self):
self.master.title('My Window2')
self.master.geometry('200x200')
self.button1.configure(text='press2', command=self.pressed2)
def pressed2(self):
self.master.wm_title('My Window3')
self.master.geometry('200x200')
self.button1.configure(text='press3', command=self.pressed3)
def pressed3(self):
print("Second window")
def close(self):
quit()
root = tkinter.Tk()
btnWindow = ButtonPressWindow(root)
btnWindow.pack(fill='both', expand=True)
root.mainloop()

Lift and raise a Canvas over a Canvas in tkinter

I'm creating a game, and I am using tkinter to build the GUI.
In this game, I want the user to start with a window, filled by a Canvas, with an image as background, and some buttons in some sort of item windows. And this Canvas is the home Canvas of the game.
The problem is that I want the user to click on a Button to land on other Canvas, who will host other things like the map or others buttons for others actions. Actually, I would like to superimpose several canvas (as in the Z-index method), and put a canvas on the top of the list, when I want it (if I click on a button for example).
I already searched and I had to change my mind several times, and now I really don't know how to do it.
I find the following code here on Stack Overflow, but it is coded for Python 2 (I think), and I'm starting coding in Python 3, so I am not able to translate it to Python 3 and solve my problem.
import Tkinter as tk
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.frame = tk.Frame(self)
self.frame.pack(side="top", fill="both", expand=True)
self.label = tk.Label(self, text="Hello, world")
button1 = tk.Button(self, text="Click to hide label",
command=self.hide_label)
button2 = tk.Button(self, text="Click to show label",
command=self.show_label)
self.label.pack(in_=self.frame)
button1.pack(in_=self.frame)
button2.pack(in_=self.frame)
def show_label(self, event=None):
self.label.lift(self.frame)
def hide_label(self, event=None):
self.label.lower(self.frame)
if __name__ == "__main__":
app = SampleApp()
app.mainloop()
My code using grid :
from tkinter import *
fenetre = Tk()
fenetre.title(my game)
# acceuil
# variable acceuil
largeur = 700
hauteur = 430
BG_acceuil = PhotoImage(file="BG_acceuil.gif")
acceuil = Canvas(fenetre, width=largeur, height=hauteur)
acceuil.create_image(0, 0, anchor=NW, image=BG_acceuil)
acceuil.grid(row=0)
acceuil.pack()
# fond
fond = PhotoImage(file="BG_acceuil.gif")
acceuil2 = Canvas(fenetre, width=largeur, height=hauteur)
acceuil2.create_image(0, 0, anchor=NW, image=fond)
acceuil2.pack()
# variable bt_jouer
x0 = 80
y0 = 230
class hide_me():
def hide_me(event, widget, pos):
widget.grid_forget()
def show_me(event, widget, pos):
widget.grid(row=pos)
# Boutton jouer
BT_jouer = Button(acceuil, text="Jouer", command=hide_me())
BT_jouer.configure(width=10, activebackground="#33B5E5", relief=GROOVE)
BT_jouer_window = acceuil.create_window(x0, y0, window=BT_jouer,)
BT_jouer.bind('<Button-1>', lambda event: hide_me(event, BT_jouer, 1))
BT_jouer.grid(row=1)
# Bouton règle
BT_regle = Button(acceuil2, text="Règles", command=fenetre.destroy)
BT_regle.configure(width=10, activebackground="#33B5E5", relief=FLAT, bd=0)
BT_regle_window = acceuil2.create_window(x0, y0 + 50, window=BT_regle)
# Boutton quitter
BT_quit = Button(acceuil, text="Quitter", command=fenetre.destroy)
BT_quit.configure(width=10, activebackground="#33B5E5", relief=FLAT)
BT_quit_window = acceuil.create_window(x0, y0 + 100, window=BT_quit)
fenetre.mainloop()
The answer is very easy: To convert to Python3, change Tkinter to tkinter, and it works!
import tkinter as tk
class SampleApp(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.frame = tk.Frame(self)
self.frame.pack(side="top", fill="both", expand=True)
self.label = tk.Label(self, text="Hello, world")
button1 = tk.Button(self, text="Click to hide label",
command=self.hide_label)
button2 = tk.Button(self, text="Click to show label",
command=self.show_label)
self.label.pack(in_=self.frame)
button1.pack(in_=self.frame)
button2.pack(in_=self.frame)
def show_label(self, event=None):
self.label.lift(self.frame)
def hide_label(self, event=None):
self.label.lower(self.frame)
def main():
app = SampleApp()
app.mainloop()
return 0
if __name__ == '__main__':
main()
Note: You are not really hiding the label - it still occupies space on the canvas. The following code, from this entry, really removes the item. It can then be recalled with a pack() call:
from Tkinter import *
def hide_me(event):
event.widget.pack_forget()
root = Tk()
btn=Button(root, text="Click")
btn.bind('<Button-1>', hide_me)
btn.pack()
btn2=Button(root, text="Click too")
btn2.bind('<Button-1>', hide_me)
btn2.pack()
root.mainloop()
I did some testing, and made an equivalent program to yours... The only problem is that the unhidden widget is always packed at the end:
from tkinter import *
def hide_me(event, widget):
widget.pack_forget()
def show_me(event, widget):
widget.pack()
root = Tk()
lbl = Label(root, text="Victim")
btn = Button(root, text="Hide the victim")
btn.bind('<Button-1>', lambda event: hide_me(event, lbl))
btn.pack()
btn2 = Button(root, text="Show the victim")
btn2.bind('<Button-1>', lambda event: show_me(event, lbl))
btn2.pack()
lbl.pack()
root.mainloop()
A better version uses the grid() packer. Here you can actually restore the 'forgotten' widget to its original position. Only slightly more complicated :)
from tkinter import *
def hide_me(event, widget, pos):
widget.grid_forget()
def show_me(event, widget, pos):
widget.grid(row = pos)
root = Tk()
lbl = Label(root, text="Victim")
lbl.grid(row = 0)
btn = Button(root, text="Hide the victim")
btn.bind('<Button-1>', lambda event: hide_me(event, lbl, 0))
btn.grid(row = 1)
btn2 = Button(root, text="Show the victim")
btn2.bind('<Button-1>', lambda event: show_me(event, lbl, 0))
btn2.grid(row = 2)
root.mainloop()
EDIT: Another observation from the comments: Bryan Oakley commented that if you use .grid_remove() instead of .grid_forget(), then the coordinates will not be lost, and a simple .grid() will restore the widget at its location.

Tkinter - RuntimeError: maximum recursion depth exceeded

I started programming in Python on Monday. I have enjoyed learning it. But I am stuck trying to understand how to avoid recursion when switching between tkinter menus! I am sure this is a very basic question, and I appreciate you tolerating my ignorance on this subject, but I have been unable to find an answer elsewhere.
What I am now doing is, eventually, giving me the error: RuntimeError: maximum recursion depth exceeded while calling a Python object
This is the pattern I am currently using. UPDATED: The code below is now a full, isolated copy reproducing the problem I am facing! :D
from tkinter import *
def mainmenu():
global frame, root
frame.destroy()
frame = Frame()
frame.pack()
button1 = Button(frame, text="anothermenulikethis", command = anothermenulikethis)
button2 = Button(frame, text="anothermenulikethis", command = anothermenulikethis)
button3 = Button(frame, text="mainmenu", command = mainmenu)
button1.pack(side=LEFT)
button2.pack(side=LEFT)
button3.pack(side=LEFT)
root.mainloop()
def anothermenulikethis():
global frame, root
frame.destroy()
frame = Frame()
frame.pack()
button1 = Button(frame, text="mainmenu", command = mainmenu)
button2 = Button(frame, text="mainmenu", command = mainmenu)
button3 = Button(frame, text="anothermenulikethis", command = anothermenulikethis)
button1.pack(side=LEFT)
button2.pack(side=LEFT)
button3.pack(side=LEFT)
root.mainloop()
root = Tk()
root.title("Recursive Menu Problem Isolation")
root.geometry("1200x600")
frame = Frame()
mainmenu()
And it all works fine, until its inevitable failure from maximum recursion depth. If anyone can suggest a better way of doing things, or has a link to an example of a better way of doing this, I am eager to learn.
PS: I have looked at and tried increasing the recursion depth, but I feel that is a poor man's solution to what is a fundamental problem with my approach.
Thank you in advance, everyone.
As requested, here is the traceback:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/tkinter/__init__.py", line 1399, in __call__
return self.func(*args)
File "/Users/diligentstudent/Desktop/menutest.py", line 11, in mainmenu
button1 = Button(frame, text="anothermenulikethis", command = anothermenulikethis)
File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/tkinter/__init__.py", line 2028, in __init__
Widget.__init__(self, master, 'button', cnf, kw)
File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/tkinter/__init__.py", line 1958, in __init__
(widgetName, self._w) + extra + self._options(cnf))
File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/tkinter/__init__.py", line 1043, in _options
v = self._register(v)
File "/Library/Frameworks/Python.framework/Versions/3.2/lib/python3.2/tkinter/__init__.py", line 1079, in _register
f = CallWrapper(func, subst, self).__call__
RuntimeError: maximum recursion depth exceeded
Only one mainloop() is needed to handle a tkinter GUI.
With that said, I think you just need an example of the class structure:
from tkinter import Tk,Button
class Application(Tk):
def say_hi(self):
print('Hello world?!')
def close_app(self):
self.destroy()
def create_Widgets(self):
self.quitButton = Button(self, width=12, text='Quit', bg='tan',
command=self.close_app)
self.quitButton.grid(row=0, column=0, padx=8, pady=8)
self.helloButton = Button(self, width=12, text='Hello',
command=self.say_hi)
self.helloButton.grid(row=0, column=1, padx=8, pady=8)
def __init__(self):
Tk.__init__(self)
self.title('Hello world!')
self.create_Widgets()
app = Application()
app.mainloop()
To avoid possible conflicts with other modules, some people prefer importing like this
(clearly stating where everything comes from):
import tkinter as tk
class Application(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title('Hello world!')
self.quitButton = tk.Button(self, width=12, text='Quit', bg='tan',
command=self.close_app)
self.quitButton.grid(row=0, column=0, padx=8, pady=8)
self.helloButton = tk.Button(self, width=12, text='Hello',
command=self.say_hi)
self.helloButton.grid(row=0, column=1, padx=8, pady=8)
def say_hi(self):
print('Hello world?!')
def close_app(self):
self.destroy()
app = Application()
app.mainloop()
And as you can see, creating the widgets can easily happen in the __init__
I decided to make a more practical / educational example based on what I've learned in the past month. While doing so I had a bit of a revelation: not everything requires a self. prefix in a class! This is especially true with a tkinter class, because you aren't manipulating it as an object in the main program. Mostly you need the self. prefix when you are going to use something in a method later. The previous examples display how anything (like the buttons) can receive a self. prefix, even when completely unnecessary.
Some things this example will show:
• pack() and grid() can be used in the same GUI as long as they don't share a master.
• A Text widget can be made to not expand when the font size changes.
• How to toggle a bold tag on and off of selected text.
• How to truly center a GUI on the screen. (more information here)
• How to make a Toplevel window appear in the same location relative to the main window.
• Two ways to prevent a Toplevel window from being destroyed, so it only needs to be created once.
• Make ctrl+a (select all) function properly.
import tkinter as tk
import tkFont
class Application(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.title('T-Pad')
# Menubar
menubar = tk.Menu(self)
filemenu = tk.Menu(menubar, tearoff=0)
filemenu.add_command(label="Exit", command=self.close_app)
menubar.add_cascade(label="File", menu=filemenu)
formatmenu = tk.Menu(menubar, tearoff=0)
formatmenu.add_command(label="Font", command=self.show_sizeWin)
menubar.add_cascade(label="Format", menu=formatmenu)
self.config(menu=menubar)
# Bold Button
boldButton = tk.Button(self, width=12, text='Bold',
command=self.make_bold)
boldButton.pack()
# Text widget, its font and frame
self.defaultFont = tkFont.Font(name="defFont")
textFrame = tk.Frame(self, borderwidth=1, relief="sunken",
width=600, height=600)
textFrame.grid_propagate(False) # ensures a consistent GUI size
textFrame.pack(side="bottom", fill="both", expand=True)
self.mText = tk.Text(textFrame, width=48, height=24, wrap='word',
font="defFont")
self.mText.grid(row=0, column=0, sticky="nsew")
# Scrollbar and config
tScrollbar = tk.Scrollbar(textFrame, command=self.mText.yview)
tScrollbar.grid(row=0, column=1, sticky='nsew', pady=1)
self.mText.config(yscrollcommand=tScrollbar.set)
# Stretchable
textFrame.grid_rowconfigure(0, weight=1)
textFrame.grid_columnconfigure(0, weight=1)
# Bold Tag
self.bold_font = tkFont.Font(self.mText, self.mText.cget("font"))
self.bold_font.configure(weight="bold")
self.mText.tag_configure("bt", font=self.bold_font)
# Center main window
self.update_idletasks()
xp = (self.winfo_screenwidth() / 2) - (self.winfo_width() / 2) - 8
yp = (self.winfo_screenheight() / 2) - (self.winfo_height() / 2) - 30
self.geometry('{0}x{1}+{2}+{3}'.format(self.winfo_width(), self.winfo_height(),
xp, yp))
# Font Size Window (notice that self.sizeWin is given an alias)
sizeWin = self.sizeWin = tk.Toplevel(self, bd=4, relief='ridge')
self.sizeList = tk.Listbox(sizeWin, width=10, height=17, bd=4,
font=("Times", "16"), relief='sunken')
self.sizeList.grid()
doneButton = tk.Button(sizeWin, text='Done', command=sizeWin.withdraw)
doneButton.grid()
for num in range(8,25):
self.sizeList.insert('end', num)
sizeWin.withdraw()
sizeWin.overrideredirect(True) # No outerframe!
# Below is another way to prevent a TopLevel window from being destroyed.
# sizeWin.protocol("WM_DELETE_WINDOW", self.callback)
# Bindings
# Double click a font size in the Listbox
self.sizeList.bind("<Double-Button-1>", self.choose_size)
self.bind_class("Text", "<Control-a>", self.select_all)
## def callback(self):
## self.sizeWin.withdraw()
def select_all(self, event):
self.mText.tag_add("sel","1.0","end-1c")
def choose_size(self, event=None):
size_retrieved = self.sizeList.get('active')
self.defaultFont.configure(size=size_retrieved)
self.bold_font.configure(size=size_retrieved)
def show_sizeWin(self):
self.sizeWin.deiconify()
xpos = self.winfo_rootx() - self.sizeWin.winfo_width() - 8
ypos = self.winfo_rooty()
self.sizeWin.geometry('{0}x{1}+{2}+{3}'.format(self.sizeWin.winfo_width(),
self.sizeWin.winfo_height(), xpos, ypos))
def make_bold(self):
try:
current_tags = self.mText.tag_names("sel.first")
if "bt" in current_tags:
self.mText.tag_remove("bt", "sel.first", "sel.last")
else:
self.mText.tag_add("bt", "sel.first", "sel.last")
except tk.TclError:
pass
def close_app(self):
self.destroy()
app = Application()
app.mainloop()
A note to others with this issue: your command for your button may not be at the proper indentation level! Check that it is inline with your other class methods before digging any further. I ran into this issue myself not long ago, and re-checking my indentations fixed everything.

Categories