i have written the "instruction" for my tkinter program on a .txt file and when the Instruction button is pressed, I would like a separate window to be created with the instruction copied from the text file into the output box.
I would be very grateful if anyone could help me.
this is what I have done so far but it doesn't work at all.
instructionBtn = Button(window, text="?", command=start, height = 5, width =30,fg="black", bg="lime green", font=("Comic Sans MS", 10))
instructionBtn.grid(row=29, column=1, sticky=S)
window.mainloop()
def instruction():
instructionwindow = Tk() #create window
instructionwindow.geometry("500x350")
instructionwindow.title("Instruction")
instructionwindow.configure(background='white')
instructionFile=open("Instruction.txt","r")
instruction.read
textboxOutput = Text(window, wrap="Instruction.txt", width = 150, height = 20)
textboxOutput.grid(row = 20, column = 0, columnspan=10)
instruction.mainloop()
When I want a second window, often a message box will do the trick, like so:
from Tkinter import *
from tkMessageBox import showinfo
class App:
def __init__(self, master):
frame = Frame(master)
frame.pack()
self.button = Button(frame, text="QUIT", fg="red", command=frame.quit)
self.button.pack(side=LEFT)
self.instr = Button(frame, text="Instruction", command=self.instruction)
self.instr.pack(side=LEFT)
def instruction(self):
try:
with open("instruction.txt") as fp:
message = fp.read()
except IOError:
message = 'No instructions available'
showinfo("Instructions", message)
root = Tk()
app = App(root)
root.mainloop()
Or, if you prefer an OOP style:
# template: https://stackoverflow.com/a/17470842/8747
# Use Tkinter for python 2, tkinter for python 3
import Tkinter as tk
import tkMessageBox
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
self.button = tk.Button(
self, text="QUIT", fg="red", command=self.quit)
self.instr = tk.Button(
self, text="Instruction", command=self.instruction)
self.button.pack(side=tk.LEFT)
self.instr.pack(side=tk.LEFT)
def instruction(self):
try:
with open("instruction.txt") as fp:
message = fp.read()
except IOError:
message = 'No instruction available'
msg = tkMessageBox.showinfo("Instruction", message)
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root).pack(side="top", fill="both", expand=True)
root.mainloop()
Of course, sometimes a message box isn't flexible enough, and you need to create a top-level window:
# template: https://stackoverflow.com/a/17470842/8747
# Use Tkinter for python 2, tkinter for python 3
import Tkinter as tk
import tkMessageBox
class Instruction(tk.Toplevel):
def __init__(self, parent, message, *args, **kwargs):
tk.Toplevel.__init__(self, parent, *args, **kwargs)
self.msg = tk.Message(self, text=message)
self.button = tk.Button(self, text="Dismiss", command=self.destroy)
self.msg.pack()
self.button.pack()
class MainApplication(tk.Frame):
def __init__(self, parent, *args, **kwargs):
tk.Frame.__init__(self, parent, *args, **kwargs)
self.parent = parent
self.button = tk.Button(
self, text="QUIT", fg="red", command=self.quit)
self.instr = tk.Button(
self, text="Instruction", command=self.instruction)
self.button.pack(side=tk.LEFT)
self.instr.pack(side=tk.LEFT)
def instruction(self):
try:
with open("instruction.txt") as fp:
message = fp.read()
except IOError:
message = 'No instruction available'
msg = Instruction(self, message)
if __name__ == "__main__":
root = tk.Tk()
MainApplication(root).pack(side="top", fill="both", expand=True)
root.mainloop()
Related
I’m trying to test the existence of a toplevel using the winfo_exists() method made available by Tkinter.
However, I cannot test the existence of a Toplevel by passing the name of this to winfo_exists() method.
I enclose a script to better clarify what I would like to do.
When you open the app, four buttons are shown. Pressing on the first appears a mask where we can, by pressing the relevant buttons, see the execution of both the winfo_exists() method and the winfo_children() method.
Selecting a Toplevel to test using the radiobox on the right happens that if the relative Toplevel is open the function work fine, otherwise generates the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "/home/bc/Desktop/simple_app.py", line 113, in on_test_exist
if self.nametowidget(DICT_TOPLEVELS[self.option.get()]).winfo_exists():
File "/usr/lib/python3.7/tkinter/__init__.py", line 1353, in nametowidget
w = w.children[n]
KeyError: 'toptwo'
Do you have any suggestions?
Basically in an application with many Toplevels, how do you see if a certain Toplevel is open?
Thank you for your attention.
#!/usr/bin/python3
import sys
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
DICT_TOPLEVELS = {0:".topone",
1:".toptwo",
2:".topthree"}
class Main(ttk.Frame):
def __init__(self, parent, ):
super().__init__(name="main")
self.parent = parent
self.init_ui()
def init_ui(self):
f0 = tk.Frame(self)
bts = [("Top One", 4, self.on_open_one, "<Alt-o>"),
("Top Two", 4, self.on_open_two, "<Alt-t>"),
("Top Three", 5, self.on_open_three, "<Alt-w>"),
("Close", 0, self.parent.on_exit, "<Alt-c>")]
for btn in bts:
ttk.Button(f0,
text=btn[0],
underline=btn[1],
command = btn[2]).pack(fill=tk.X, padx=5, pady=5)
self.parent.bind(btn[3], btn[2])
f0.pack()
def on_open_one(self, evt=None):
obj = TopOne(self)
obj.on_open()
def on_open_two(self, evt=None):
obj = TopTwo(self)
obj.on_open()
def on_open_three(self, evt=None):
obj = TopThree(self)
obj.on_open()
class TopOne(tk.Toplevel):
def __init__(self, parent,):
super().__init__(name="topone")
self.parent = parent
self.minsize(200, 100)
self.voices = ('topone','toptwo','topthree')
self.option = tk.IntVar()
self.init_ui()
def init_ui(self):
f0 = tk.Frame(self, bg='SlateGray4', padx=5,pady=5)
f1 = tk.Frame(f0,)
bts = [("Call winfo_exists", 7, self.on_winfo_exists, "<Alt-c>"),
("Get winfo_children", 0, self.on_get_winfo_children, "<Alt-g>"),
("Test exist", 0, self.on_test_exist, "<Alt-t>"),
("Close", 0, self.master.on_exit, "<Alt-c>")]
for btn in bts:
ttk.Button(f1,
text=btn[0],
underline=btn[1],
command = btn[2]).pack(fill=tk.X, padx=5, pady=5)
self.parent.bind(btn[3], btn[2])
f2 = tk.Frame(f0,)
ttk.Label(f2, text="Toplevels:").pack()
for index, text in enumerate(self.voices):
ttk.Radiobutton(f2,
text=text,
variable=self.option,
value=index,).pack()
f0.pack(fill=tk.BOTH, expand=1, padx=5, pady=5)
f2.pack(side=tk.RIGHT, fill=tk.Y, padx=5, pady=5, expand=0)
f1.pack(side=tk.LEFT, fill=tk.Y, padx=5, pady=5, expand=0)
def on_open(self):
msg = "{0}".format(self.winfo_name().title())
self.title(msg)
def on_winfo_exists(self, evt=None):
for obj in self.nametowidget(".").winfo_children():
if self.nametowidget(obj).winfo_exists():
print("{0} is exist!".format(self.nametowidget(obj).winfo_name()))
def on_get_winfo_children(self, evt=None):
for obj in self.nametowidget(".").winfo_children():
print(self.master.nametowidget(obj))
def on_test_exist(self):
print("You have selected to test if {0} Toplevel exist.".format(DICT_TOPLEVELS[self.option.get()]),)
if self.nametowidget(DICT_TOPLEVELS[self.option.get()]).winfo_exists():
print("Well Toplevel named {0} exists!".format(self.nametowidget(DICT_TOPLEVELS[self.option.get()]).winfo_name()))
else:
print("I’m sorry but Toplevel named {0} doesn’t exist!".format(DICT_TOPLEVELS[self.option.get()]))
class TopTwo(tk.Toplevel):
def __init__(self, parent,):
super().__init__(name="toptwo")
self.parent = parent
self.minsize(200, 100)
self.init_ui()
def init_ui(self):
f = tk.Frame(self, bg='DarkSeaGreen4', padx=5,pady=5)
f.pack(fill=tk.BOTH, expand=1, padx=5, pady=5)
def on_open(self):
msg = "{0}".format(self.winfo_name().title())
self.title(msg)
class TopThree(tk.Toplevel):
def __init__(self, parent,):
super().__init__(name="topthree")
self.parent = parent
self.minsize(200, 100)
self.init_ui()
def init_ui(self):
f = tk.Frame(self, bg='DarkSeaGreen3', padx=5,pady=5)
f.pack(fill=tk.BOTH, expand=1, padx=5, pady=5)
def on_open(self):
msg = "{0}".format(self.winfo_name().title())
self.title(msg)
class App(tk.Tk):
"""Main Application start here"""
def __init__(self,):
super().__init__()
self.protocol("WM_DELETE_WINDOW", self.on_exit)
#self.resizable(width=False, height=False)
self.geometry('400x200')
self.title("Simple App")
Main(self).pack(fill=tk.BOTH, expand=1)
def on_exit(self):
msg = "Do you want to quit?"
if messagebox.askokcancel(self.title(), msg, parent=self):
self.destroy()
def main():
app = App()
app.mainloop()
if __name__ == '__main__':
main()
I am working with tkinter's class-based structure and I need to get a value of text input. How do I do that?
Here is the relevant code:
#GUI
class PseudostreamWidget(tk.Frame):
def __init__(self, master=None, **kw):
tk.Frame.__init__(self, master, **kw)
self.targetIP = tk.Entry(self.Ipconfig)
self.targetIP.configure(background='black', font='{Lato} 12 {}', foreground='white', highlightbackground='black')
self.targetIP.configure(highlightcolor='black', justify='left', relief='raised')
_text_ = '''Friend's Public IP Here'''
self.targetIP.delete('0', 'end')
self.targetIP.insert('0', _text_)
self.targetIP.grid(column='1', row='0')
#
#
#
target_ip = self.targetIP
#
#
How do I get it to print target_ip outside the class?
if __name__ == '__main__':
root = tk.Tk()
widget = PseudostreamWidget(root)
widget.pack(expand=True, fill='both')
root.mainloop()
print(target_ip)
Try this:
import tkinter as tk
class PseudostreamWidget(tk.Frame):
def __init__(self, master=None, callback=None, **kwargs):
super().__init__(master, **kwargs)
self.targetIP = tk.Entry(self, fg="white", justify="left",
relief="raised", highlightbackground="black",
highlightcolor="black", bg="black",
insertbackground="white", font=("Lato", 12))
# self.targetIP.delete(0, "end") # No need for this
self.targetIP.insert(0, "Friend's Public IP Here")
self.targetIP.grid(column=1, row=0)
self.targetIP.bind("<Return>", callback)
def submit_data(event=None):
print("You typed in:", widget.targetIP.get())
root = tk.Tk()
widget = PseudostreamWidget(root, callback=submit_data)
widget.pack()
root.mainloop()
To use it just write something inside the entry and press the Enter key on your keyboard.
It passes in a function (submit_data) and binds to it.
If I create a Toplevel popup window in a tkinter application, when I close the main root window all sub windows are closed.
With the following code, if I open up two successive Toplevel windows, I can close "Window One" but "Window Two" stays open.
#!/usr/bin/env python3
import tkinter as tk
import tkinter.ttk as ttk
def main():
root = tk.Tk()
root.geometry("600x300")
root.title("Main Window")
app = Application(root)
app.mainloop()
def window_one():
window_one = WindowOne()
window_one.geometry("450x200")
window_one.title('Window One')
def window_two():
window_two = WindowTwo()
window_two.geometry("200x100")
window_two.title('Window Two')
class Application(ttk.Frame):
def __init__(self, master= None, *args, **kwargs):
super().__init__(master = master)
self.pack()
self.create_widgets()
def create_widgets(self):
button1 = ttk.Button(self, text = "Click Here", command = window_one)
button1.pack()
class WindowOne(tk.Toplevel):
def __init__(self, master= None, *args, **kwargs):
super().__init__(master = master)
self.create_widgets()
def create_widgets(self):
button1 = ttk.Button(self, text = "Click Here", command = window_two)
button1.pack()
class WindowTwo(tk.Toplevel):
def __init__(self, master= None, *args, **kwargs):
super().__init__(master = master)
self.create_widgets()
def create_widgets(self):
button1 = ttk.Button(self, text = "$$$")
button1.pack()
if __name__ == "__main__":
main()
How can I code this to make Window Two dependent on Window One so that if I close "Window One", "Window Two" also closes, mimicking the behaviour of the main root window?
You can make Window One the parent of Window Two:
def window_two(parent):
window_two = WindowTwo(parent) # pass parent to WindowTwo
window_two.geometry("200x100")
window_two.title('Window Two')
...
class WindowOne(tk.Toplevel):
def __init__(self, master= None, *args, **kwargs):
super().__init__(master = master)
self.create_widgets()
def create_widgets(self):
button1 = ttk.Button(self, text = "Click Here", command = lambda: window_two(self)) # pass self to `window_two()`
button1.pack()
Update: if you want to close Window One when Window Two is closed, you can use self.protocol("WM_DELETE_WINDOW", ...):
class WindowTwo(tk.Toplevel):
def __init__(self, master= None, *args, **kwargs):
super().__init__(master = master)
self.create_widgets()
self.protocol("WM_DELETE_WINDOW", self.on_destroy)
def create_widgets(self):
button1 = ttk.Button(self, text = "$$$")
button1.pack()
def on_destroy(self):
self.master.destroy() # close parent window
self.destroy() # close itself
or bind <Destroy> event to a callback to close the parent window:
class WindowTwo(tk.Toplevel):
def __init__(self, master= None, *args, **kwargs):
super().__init__(master = master)
self.create_widgets()
self.bind("<Destroy>", self.on_destroy)
def create_widgets(self):
button1 = ttk.Button(self, text = "$$$")
button1.pack()
def on_destroy(self, event):
self.master.destroy() # close parent window
Can anyone help me to understand the window code? Im trying to make all the objects run in a Toplevel() function instead of a new instance of Tkinter because that doesn't work launching it from another program. Theres no window = Tk() function anywhere just init and frame.
from tkinter import *
from tkinter.simpledialog import askstring
from tkinter.filedialog import asksaveasfilename
from tkinter.messagebox import askokcancel
def text_edit() :
class Quitter(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.pack()
widget = Button(self, text='Quit', command=self.quit)
widget.pack(expand=YES, fill=BOTH, side=LEFT)
def quit(self):
ans = askokcancel('Verify exit', "Really quit?")
if ans: Frame.quit(self)
class ScrolledText(Frame):
def __init__(self, parent=None, text='', file=None):
Frame.__init__(self, parent)
self.pack(expand=YES, fill=BOTH)
self.makewidgets()
self.settext(text, file)
def makewidgets(self):
sbar = Scrollbar(self)
text = Text(self, relief=SUNKEN)
sbar.config(command=text.yview)
text.config(yscrollcommand=sbar.set)
sbar.pack(side=RIGHT, fill=Y)
text.pack(side=LEFT, expand=YES, fill=BOTH)
self.text = text
def settext(self, text='', file=None):
if file:
text = open(file, 'r').read()
self.text.delete('1.0', END)
self.text.insert('1.0', text)
self.text.mark_set(INSERT, '1.0')
self.text.focus()
def gettext(self):
return self.text.get('1.0', END+'-1c')
class SimpleEditor(ScrolledText):
def __init__(self, parent=None, file=None):
frm = Frame(parent)
frm.pack(fill=X)
Button(frm, text='Save', command=self.onSave).pack(side=LEFT)
Button(frm, text='Cut', command=self.onCut).pack(side=LEFT)
Button(frm, text='Paste', command=self.onPaste).pack(side=LEFT)
Button(frm, text='Find', command=self.onFind).pack(side=LEFT)
Quitter(frm).pack(side=LEFT)
ScrolledText.__init__(self, parent, file=file)
self.text.config(font=('courier', 9, 'normal'))
def onSave(self):
filename = asksaveasfilename()
if filename:
alltext = self.gettext()
open(filename, 'w').write(alltext)
def onCut(self):
text = self.text.get(SEL_FIRST, SEL_LAST)
self.text.delete(SEL_FIRST, SEL_LAST)
self.clipboard_clear()
self.clipboard_append(text)
def onPaste(self):
try:
text = self.selection_get(selection='CLIPBOARD')
self.text.insert(INSERT, text)
except TclError:
pass
def onFind(self):
target = askstring('SimpleEditor', 'Search String?')
if target:
where = self.text.search(target, INSERT, END)
if where:
print (where)
pastit = where + ('+%dc' % len(target))
#self.text.tag_remove(SEL, '1.0', END)
self.text.tag_add(SEL, where, pastit)
self.text.mark_set(INSERT, pastit)
self.text.see(INSERT)
self.text.focus()
if __name__ == '__main__':
try:
SimpleEditor(file=sys.argv[1]).mainloop()
except IndexError:
SimpleEditor().mainloop()
You have to adapt to Tkinter as it was written to be used (or write your own which is beyond me), instead of trying to pound it into some preconceived form.
try:
import Tkinter as tk ## Python 2.x
except ImportError:
import tkinter as tk ## Python 3.x
from functools import partial
class OpenToplevels():
""" open and close additional Toplevels with a button
"""
def __init__(self):
self.root = tk.Tk()
self.button_ctr=0
but=tk.Button(self.root, text="Open a Toplevel",
command=self.open_another)
but.grid(row=0, column=0)
tk.Button(self.root, text="Exit Tkinter", bg="red",
command=self.root.quit).grid(row=1, column=0, sticky="we")
self.root.mainloop()
def close_it(self, id):
id.destroy()
def open_another(self):
self.button_ctr += 1
id = tk.Toplevel(self.root)
id.title("Toplevel #%d" % (self.button_ctr))
tk.Button(id, text="Close Toplevel #%d" % (self.button_ctr),
command=partial(self.close_it, id),
bg="orange").grid(row=1, column=0)
Ot=OpenToplevels()
I'm trying to add a "Done" button to my program that will print the content of both Entry widgets to a new box. I can get the button to appear, but I can't get the information to show up in a new box. What am I doing wrong?
from Tkinter import *
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.grid()
self._name = StringVar()
self._name.set("Enter name here")
self._age = IntVar()
self._age.set("Enter age here")
top = self.winfo_toplevel() # find top-level window
top.title("Entry Example")
self._createWidgets()
self._button = Button(self,
text = "Done")
self._button.grid(row = 1, column = 0, columnspan = 2)
def _createWidgets(self):
textEntry = Entry(self, takefocus=1,
textvariable = self._name, width = 40)
textEntry.grid(row=0, sticky=E+W)
ageEntry = Entry(self, takefocus=1,
textvariable = self._age, width = 20)
ageEntry.grid(row=1, sticky=W)
def _widget(self):
tkMessageBox.showinfo
# end class Application
def main():
Application().mainloop()
You need to assign an action to your button using command: option.
To get what is written in Entry you need to use get() method.
showinfo you need two arguments, one is the title, the other one is what is going to be shown.
Also you need to import tkMessageBox.
Here is a working example.
import Tkinter as tk
import tkMessageBox
class Example(tk.Frame):
def __init__(self,root):
tk.Frame.__init__(self, root)
self.txt = tk.Entry(root)
self.age = tk.Entry(root)
self.btn = tk.Button(root, text="Done", command=self.message)
self.txt.pack()
self.age.pack()
self.btn.pack()
def message(self):
ent1 = self.txt.get()
ent2 = self.age.get()
tkMessageBox.showinfo("Title","Name: %s \nAge: %s" %(ent1,ent2))
if __name__=="__main__":
root = tk.Tk()
root.title("Example")
example = Example(root)
example.mainloop()