from tkinter import *
master = Tk()
def managerMode():
print ("Connecting to Manager Mode... please wait")
def employeeMode():
print ("Connecting to Employee Mode... please wait")
b = Button(master, text="Manager Mode", command = managerMode)
b.pack()
c = Button(master,text="Employee Mode", command=employeeMode)
c.pack()
mainloop()
This is my code, and I am planning to close window that contains the types of mode when the user picks one of those options, "Manager Mode" or "Employee Mode". How can I continue closing the button window?
Use the destroy method.
import tkinter
from tkinter import ttk
class MyApp:
def __init__(self):
self.root = tkinter.Tk()
def startman(self):
self.root.destroy() # like this
self.root = tkinter.Tk()
self.root.title('Manager Mode')
self.backbutton = ttk.Button(self.root, text='Back', command=self.startmenu)
self.backbutton.grid(column=0, row=0, sticky='nsew')
self.root.mainloop()
def startemp(self):
self.root.destroy() # or this
self.root = tkinter.Tk()
self.root.title('Employee Mode')
self.backbutton = ttk.Button(self.root, text='Back', command=self.startmenu)
self.backbutton.grid(column=0, row=0, sticky='nsew')
self.root.mainloop()
def startmenu(self):
self.root.destroy() # or this
self.root = tkinter.Tk()
self.root.title('Mode Selection')
self.manbutton = ttk.Button(self.root, text='Manager Mode', command=self.startman)
self.empbutton = ttk.Button(self.root, text='Employee Mode', command=self.startemp)
self.manbutton.grid(column=0, row=0, sticky='nsew')
self.empbutton.grid(column=0, row=1, sticky='nsew')
self.root.mainloop()
def run(self):
self.startmenu()
MyApp().run()
Related
I am stuck at referencing methods and variables between classes in Tkinter.
Here is an simple example, I have three different types of windows, which I would like to put into different classes.
In the root window, I can click the button to open the second window, where I can input something in to the Text widget.
Also in the 2nd window I want the OK button to read the content in the Text widget and insert the content into another Text widget into the 3rd window. And the Cancel button can close the 2nd window and show the root window again.
There is many bugs in the code, because I couldn't figure out how to make cross references between classes to access the methods and variables.
Could anyone help me to accomplish that? Thanks.
from tkinter import *
from tkinter import scrolledtext
def main():
"""The main app function"""
root = Tk()
root_window = Root(root)
return None
class Root:
def __init__(self, root):
# Main root window configration
self.root = root
self.root.geometry("200x100")
self.btn_ok = Button(self.root, text="Open new window",
command=NewWindow)
self.btn_ok.pack(padx=10, pady=10)
def hide(self):
"""Hide the root window."""
self.root.withdraw()
def show(self):
"""Show the root window from the hide status"""
self.root.update()
self.root.deiconify()
def onClosing(self, window):
window.destroy()
self.show()
class NewWindow:
def __init__(self):
Root.hide()
self.new_window = Toplevel()
lbl = Label(self.new_window, text="Input here:")
lbl.pack(padx=10, pady=(10, 0), anchor=W)
# Create a scrolledtext widget.
self.new_content = scrolledtext.ScrolledText(
self.new_window, wrap=WORD,
)
self.new_content.pack(padx=10, expand=True, fill=BOTH, anchor=W)
# Respond to the 'Cancel' button.
btn_cancel = Button(self.new_window, text="Cancel", width=10,
command=lambda: Root.onClosing(self.new_window))
btn_cancel.pack(padx=10, pady=10, side=RIGHT)
# Add 'OK' button to read sequence
self.btn_ok = Button(self.new_window, text="OK", width=10,
command=WorkingWindow)
self.btn_ok.pack(padx=10, pady=10, side=RIGHT)
def readContent(self):
self.content = self.new_content.get(1.0, END)
self.new_window.destroy()
workwindow = WorkingWindow()
class WorkingWindow:
def __init__(self):
self.work_window = Toplevel()
self.work_content = scrolledtext.ScrolledText(self.work_window, wrap=WORD, font=("Courier New", 11))
self.work_content.pack(padx=10, expand=True, fill=BOTH, anchor=W)
self.work_content.insert(1.0, Root.content)
if __name__ == '__main__':
main()
You were almost there all you have to do is pass the instance of Root class to other class you are calling
Here is the corrected code:
from tkinter import *
from tkinter import scrolledtext
def main():
"""The main app function"""
root = Tk()
root_window = Root(root)
root.mainloop()
class Root:
def __init__(self, root):
# Main root window configration
self.root = root
self.root.geometry("200x100")
self.btn_ok = Button(self.root, text="Open new window",
command=lambda :NewWindow(self))
self.btn_ok.pack(padx=10, pady=10)
def hide(self):
"""Hide the root window."""
self.root.withdraw()
def show(self):
"""Show the root window from the hide status"""
self.root.update()
self.root.deiconify()
def onClosing(self, window):
window.destroy()
self.show()
class NewWindow:
def __init__(self, parent):
parent.hide()
self.new_window = Toplevel()
lbl = Label(self.new_window, text="Input here:")
lbl.pack(padx=10, pady=(10, 0), anchor=W)
# Create a scrolledtext widget.
self.new_content = scrolledtext.ScrolledText(
self.new_window, wrap=WORD,
)
self.new_content.pack(padx=10, expand=True, fill=BOTH, anchor=W)
# Respond to the 'Cancel' button.
btn_cancel = Button(self.new_window, text="Cancel", width=10,
command=lambda: parent.onClosing(self.new_window))
btn_cancel.pack(padx=10, pady=10, side=RIGHT)
# Add 'OK' button to read sequence
self.btn_ok = Button(self.new_window, text="OK", width=10,
command=self.readContent)
self.btn_ok.pack(padx=10, pady=10, side=RIGHT)
def readContent(self):
self.content = self.new_content.get(1.0, END)
self.new_window.destroy()
workwindow = WorkingWindow(self)
class WorkingWindow:
def __init__(self, parent):
self.work_window = Toplevel()
self.work_content = scrolledtext.ScrolledText(self.work_window, wrap=WORD, font=("Courier New", 11))
self.work_content.pack(padx=10, expand=True, fill=BOTH, anchor=W)
self.work_content.insert(1.0, parent.content)
if __name__ == '__main__':
main()
I created a window with tkinter for my programm but I want it to resize itself when the user resizes the window. Right now when I increase or decrease the size of the window the widgets stay at the same position and don't in-/decrease in size.
Here is my code:
import tkinter as tk
class Graphicaluserinterface(tk.Frame):
def __init__(self,master=None):
super().__init__(master)
self.grid()
self.check1 = tk.IntVar()
self.fileopenname1 = tk.StringVar()
self.entrystring = tk.IntVar()
self.menubar = tk.Menu(self)
self.create_widgets()
def create_widgets(self):
self.filemenu=tk.Menu(self.menubar,tearoff=0)
self.menubar.add_cascade(label="File",menu=self.filemenu)
self.filemenu.add_command(label="Exit",command = root.destroy)
self.helpmenu=tk.Menu(self.menubar,tearoff=0)
self.programmstart = tk.Button(self, text = "Start Program")
self.programmstart.grid(row=10,column=8,sticky = "W")
self.checkbutton1 = tk.Checkbutton(self, text = "Drehzahl und Drehmoment",variable=self.check1,onvalue=1,offvalue=0)
self.checkbutton1.grid(row=0,column=0,columnspan=3,sticky = "W")
self.leer1 = tk.Label(self,text=" ") #erzeugt leere Zelle, sonst ist startbutton links
self.leer1.grid(row=0,column=3,columnspan=5)
self.leer2 = tk.Label(self,text=" ")
self.leer2.grid(row=5,column=8,rowspan=2)
self.leer3 = tk.Label(self,text=" ")
self.leer3.grid(row=9,column=9)
self.inputpathdisplay = tk.Label(self,textvariable=self.fileopenname1,bg="white",width=60)
self.inputpathdisplay.grid(row=1,column=8,columnspan=3,sticky = "W")
self.inputpathdisplaylabel = tk.Label(self,text="Inputfile")
self.inputpathdisplaylabel.grid(row=0,column=8,columnspan=3)
root = tk.Tk()
app = Graphicaluserinterface(master=root)
app.master.title("Programm")
app.master.minsize(800,300)
root.config(menu=app.menubar)
app.mainloop()
You need to configure the weight on your grid's rows and columns. The following is a refactored version of your code that should act a little more as you were hoping. Please continue development from this code:
#! /usr/bin/env python3
import tkinter
from tkinter.constants import *
class GraphicalUserInterface(tkinter.Frame):
#classmethod
def main(cls):
root = tkinter.Tk()
root.title('Program')
root.minsize(560, 105)
gui = cls(root)
gui.grid(row=0, column=0, sticky=NSEW)
root.grid_rowconfigure(0, weight=1)
root.grid_columnconfigure(0, weight=1)
root['menu'] = gui.menubar
cls.create_toplevel(root, 'First Toplevel')
root.mainloop()
#staticmethod
def create_toplevel(root, window_title):
window = tkinter.Toplevel(root)
window.title(window_title)
window.minsize(560, 105)
def __init__(self, master=None):
super().__init__(master)
self.check_value = tkinter.BooleanVar()
self.filename = tkinter.StringVar()
self.menubar = tkinter.Menu(self)
self.file_menu = tkinter.Menu(self.menubar, tearoff=FALSE)
self.help_menu = tkinter.Menu(self.menubar, tearoff=FALSE)
self.program_start = tkinter.Button(
self, text='Start Program',
command=lambda: self.create_toplevel(self.master, 'Another Window')
)
self.check_button = tkinter.Checkbutton(
self, text='Speed & Torque', variable=self.check_value,
onvalue=True, offvalue=False
)
self.input_path_display = tkinter.Label(
self, textvariable=self.filename, bg='white', width=60
)
self.input_path_display_label = tkinter.Label(self, text='Input File')
self.create_widgets()
def create_widgets(self):
self.menubar.add_cascade(label='File', menu=self.file_menu)
self.file_menu.add_command(label='Exit', command=self.master.destroy)
pad = dict(padx=5, pady=5)
self.check_button.grid(row=0, column=0, **pad)
self.input_path_display_label.grid(row=0, column=1, sticky=EW, **pad)
self.input_path_display.grid(row=1, column=1, sticky=NSEW, **pad)
self.program_start.grid(row=2, column=1, sticky=EW, **pad)
self.grid_rowconfigure(1, weight=1)
self.grid_columnconfigure(1, weight=1)
if __name__ == '__main__':
GraphicalUserInterface.main()
I have the following code to generate a two entry input dialog box and a button to close the "app".
However I cannot cannot get the values out of the outputs. They always come out as x and N. The code was not developed by me since I am a beginner with python. Can anyone give me hand with this?
from tkinter import Tk, Text, TOP, BOTH, X, N, LEFT, RIGH
from tkinter.ttk import Frame, Label, Entry, Button
class SimpleDialog(Frame):
def __init__(self):
super().__init__()
self.output1 = ""
self.output2 = ""
self.initUI()
def initUI(self):
self.master.title("Simple Dialog")
self.pack(fill=BOTH, expand=True)
frame1 = Frame(self)
frame1.pack()
lbl1 = Label(frame1, text="Input1", width=6)
lbl1.pack(side=LEFT, padx=5, pady=10)
self.entry1 = Entry(frame1)
self.entry1.pack(padx=5, expand=True)
frame2 = Frame(self)
frame2.pack()
lbl2 = Label(frame2, text="Input2", width=6)
lbl2.pack(side=LEFT, padx=5, pady=10)
self.entry2 = Entry(frame2)
self.entry2.pack(padx=5, expand=True)
frame3 = Frame(self)
frame3.pack()
btn = Button(frame3, text="Submit", command=self.onSubmit)
btn.pack(padx=5, pady=10)
def onSubmit(self):
self.output1 = self.entry1.get()
self.output2 = self.entry2.get()
self.quit()
def main():
# This part triggers the dialog
root = Tk()
root.geometry("250x150+300+300")
app = SimpleDialog()
root.mainloop()
user_input = (app.output1, app.output2)
try:
root.destroy()
except:
pass
return user_input
if __name__ == '__main__':
main()
kind regards!
This is my code.
When i press CTRL+S it popups a TopLevel Window. However, when i press CTRL+S again, it popups up another window on top of it and so on.
How can i improve the code so that only one window Pops up when I press CTRL+S.
from tkinter import *
from tkinter import messagebox
class MainWindow(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.master.title("Tournament Software")
self.menu()
def menu(self):
menu = Menu(self.master)
self.master.config(menu=menu)
participant = Menu(menu, tearoff=False)
participant.add_command(label="Add participant", accelerator="Ctrl+S", command=self.addparticipant_window)
menu.add_cascade(label="Participants", menu=participant)
self.bind_all('<Control-s>', lambda e: menu.after(100,self.addparticipant_window))
def addparticipant_window(self):
participantWindow = Toplevel()
participantWindow.geometry("400x350")
participantWindow.resizable(False, False)
top_frame = Frame(participantWindow, bg='cyan', width=450, height=50, pady=3)
top_frame.grid(row=0, sticky="ew")
root = Tk()
root.iconbitmap("Icon.ico")
root.geometry("500x400")
root.resizable(False, False)
app = MainWindow(root)
root.mainloop()
Thankyou, I am new to this so help me.
from tkinter import *
from tkinter import messagebox
class MainWindow(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.master.title("Tournament Software")
self.menu()
self.popup = None
def open_up(self):
if self.popup is None or not self.popup.top.winfo_exists():
self.popup = addparticipant_window()
else:
self.popup.top.lift(self.master)
def menu(self):
menu = Menu(self.master)
self.master.config(menu=menu)
participant = Menu(menu, tearoff=False)
participant.add_command(label="Add participant", accelerator="Ctrl+S", command=self.open_up)
menu.add_cascade(label="Participants", menu=participant)
self.bind_all('<Control-s>', lambda e: menu.after(100,self.open_up))
class addparticipant_window:
def __init__(self):
self.top = Toplevel()
self.top.geometry("400x350")
self.top.resizable(False, False)
top_frame = Frame(self.top, bg='cyan', width=450, height=50, pady=3)
top_frame.grid(row=0, sticky="ew")
root = Tk()
root.geometry("500x400")
root.resizable(False, False)
app = MainWindow(root)
root.mainloop()
This is a tkinter program with a start/stop button to enter and exit an infinite loop that logs to a text logger widget. I cannot for the life of me figure out why, but only when the start button is pressed, the frame blinks/flashes, but the function runs fine. When I select start from the file menu, there is no flash... any ideas as to why this may be? Is it a bug in my code?
import tkinter as tk
import tkinter.scrolledtext as tkst
from tkinter import ttk
import logging
def popupmsg(msg):
popup = tk.Tk()
popup.wm_title("!")
label = ttk.Label(popup, text=msg)
label.pack(side="top", fill="x", pady=10)
b1 = ttk.Button(popup, text="Okay", command=popup.destroy)
b1.pack()
popup.mainloop()
class TextHandler(logging.Handler):
def __init__(self, text):
# run the regular Handler __init__
logging.Handler.__init__(self)
# Store a reference to the Text it will log to
self.text = text
def emit(self, record):
msg = self.format(record)
def append():
self.text.configure(state='normal')
self.text.insert(tk.END, msg + '\n')
self.text.configure(state='disabled')
# Autoscroll to the bottom
self.text.yview(tk.END)
# This is necessary because we can't modify the Text from other threads
self.text.after(0, append)
def create(self, num):
# Create textLogger
topframe = tk.Frame(root)
topframe.pack(side=tk.TOP)
if num == 0:
st = tkst.ScrolledText(topframe, state='disabled')
st.configure(font='TkFixedFont')
st.pack()
self.text_handler = TextHandler(st)
# Add the handler to logger
self.logger = logging.getLogger()
self.logger.addHandler(self.text_handler)
print(num)
else:
# Add the handler to logger
self.logger = logging.getLogger()
print(num)
def stop():
root.flag = False
def loop():
th = TextHandler("none")
th.create(1)
def start():
if root.flag:
th.logger.error("error")
root.after(1000, start)
else:
th.logger.error("Loop stopped")
root.flag = True
return
start()
class HomePage(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
#logger and main loop
th = TextHandler("none")
th.create(0)
root.flag = True
bottomframe = tk.Frame(root)
bottomframe.pack(side=tk.BOTTOM)
topframe = tk.Frame(root)
topframe.pack(side=tk.TOP)
topframe = tk.Frame(root)
topframe.pack(side=tk.TOP)
# Create taskbar/menu
taskbar = tk.Menu(self.master)
self.master.config(menu=taskbar)
file = tk.Menu(taskbar)
file.add_command(label="Run", command=loop)
file.add_command(label="Stop", command=stop)
file.add_separator()
file.add_command(label="Settings", command=lambda: popupmsg("Coming \"soon\"..."))
file.add_separator()
file.add_command(label="Quit", command=quit)
taskbar.add_cascade(label="File", menu=file)
startButton = tk.Button(bottomframe, text="Start", command=loop)
startButton.pack()
stopButton = tk.Button(bottomframe, text="Stop", command=stop)
stopButton.pack()
exitButton = tk.Button(bottomframe, text="Exit", command=quit)
exitButton.pack()
if __name__ == "__main__":
root = tk.Tk()
app = HomePage(root)
root.wm_title("Scraper")
root.mainloop()
I'm not totally sure why, but adjusting my code like so has fixed this screen blink.
I moved the stop and loop functions into the TextHandler class as methods. This allowed me to remove the second call to TextHandler and the create method that was in the loop function. I also now have no need for a second argument in the create method (was using it as a sort of flag), so that was removed.
I'm guessing the flash was this second call whenever the start button was being clicked.
import tkinter as tk
import tkinter.scrolledtext as tkst
from tkinter import ttk
import logging
def popupmsg(msg):
popup = tk.Tk()
popup.wm_title("!")
label = ttk.Label(popup, text=msg)
label.pack(side="top", fill="x", pady=10)
b1 = ttk.Button(popup, text="Okay", command=popup.destroy)
b1.pack()
popup.mainloop()
class TextHandler(logging.Handler):
def __init__(self, text):
# run the regular Handler __init__
logging.Handler.__init__(self)
# Store a reference to the Text it will log to
self.text = text
def emit(self, record):
msg = self.format(record)
def append():
self.text.configure(state='normal')
self.text.insert(tk.END, msg + '\n')
self.text.configure(state='disabled')
# Autoscroll to the bottom
self.text.yview(tk.END)
# This is necessary because we can't modify the Text from other threads
self.text.after(0, append)
def create(self):
# Create textLogger
topframe = tk.Frame(root)
topframe.pack(side=tk.TOP)
st = tkst.ScrolledText(topframe, state='disabled')
st.configure(font='TkFixedFont')
st.pack()
self.text_handler = TextHandler(st)
# Add the handler to logger
self.logger = logging.getLogger()
self.logger.addHandler(self.text_handler)
def stop(self):
root.flag = False
def loop(self):
def start():
if root.flag:
self.logger.error("error")
root.after(1000, start)
else:
self.logger.error("Loop stopped")
root.flag = True
return
start()
class HomePage(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
#logger and main loop
th = TextHandler("none")
th.create()
root.flag = True
bottomframe = tk.Frame(root)
bottomframe.pack(side=tk.BOTTOM)
topframe = tk.Frame(root)
topframe.pack(side=tk.TOP)
topframe = tk.Frame(root)
topframe.pack(side=tk.TOP)
# Create taskbar/menu
taskbar = tk.Menu(self.master)
self.master.config(menu=taskbar)
file = tk.Menu(taskbar)
file.add_command(label="Run", command=lambda: th.loop())
file.add_command(label="Stop", command=lambda: th.loop())
file.add_separator()
file.add_command(label="Settings", command=lambda: popupmsg("Coming \"soon\"..."))
file.add_separator()
file.add_command(label="Quit", command=quit)
taskbar.add_cascade(label="File", menu=file)
startButton = tk.Button(text="Start", command=lambda: th.loop())
startButton.pack()
stopButton = tk.Button(text="Stop", command=lambda: th.stop())
stopButton.pack()
exitButton = tk.Button(text="Exit", command=quit)
exitButton.pack()
if __name__ == "__main__":
root = tk.Tk()
app = HomePage(root)
root.wm_title("Scraper")
root.mainloop()
¯\_(ツ)_/¯