I have two classes with produce two separate GUI windows. I am struggling to implement a situation where e.g. if a button is pressed in the first GUI, it adds a label to the second GUI after run-time. Could someone please provide me with a solution to this?
Class CustomerOrder:
def __init__(self, master):
self.master = master
master.title("Customer Order GUI")
self.completedButton1 = Label(master,text=" Place Order:")
self.completedButton1.pack(side=TOP)
root = Tk()
my_gui = CustomerOrder(root)
root.mainloop()
class baristaPage(tk.Frame):
def __init__(self, master):
self.master = master
master.title("baristaPage")
self.baristaPage = Label(text="Barista Page")
self.baristaPage.place(x=0,y=0)
dashboard = Label(text="Customer Queue System")
dashboard.place(x=0,y=80)
root = Tk()
my_gui = baristaPage(root)
root.mainloop()
Here is a sample code that creates the Barista and the Customer windows. The Customer window contain a Button, and each time you press this button, it increments the order counter and updates the Barista window. Is this the kind of stuff that you need?
from tkinter import *
class Customer(Toplevel):
def __init__(self, master):
Toplevel.__init__(self) # create the secondary window
self.title("Customer")
self.master = master
self.counter = 0
self.customer = Label(self, text="Customer Page", width=40)
self.customer.pack(side=TOP)
self.button = Button(self, text="Place Order:", command=self.order)
self.button.pack(side=TOP)
self.mainloop()
def order(self):
self.counter += 1
self.master.dashboard['text'] = "Order number %s" % self.counter
class Barista(Tk):
def __init__(self):
Tk.__init__(self) # create the main window
self.title("Barista")
self.barista = Label(self, text="Barista Page", width=40)
self.barista.pack(side=TOP)
self.dashboard = Label(self, text="Customer Queue System")
self.dashboard.pack(side=TOP)
self.customer = Customer(self) # instantiate Customer window
self.mainloop()
Barista()
Related
Communication between objects
The idea is create a Toplevel window from Gui and after Toplevel closed send the data (name) from Toplevel Entry back to Gui
How object app can know whether the toplev object was destroyed?
or with other words
How can object of Gui know that the object of My_Toplevel is closed?
from tkinter import *
font1 = font=("Open Sans Standard",16,"bold")
class My_Toplevel():
def __init__(self, master=None):
self.master = master
self.toplev = Toplevel(master)
self.name = None
self.create_widgets()
def create_widgets(self):
self.entry_name = Entry(self.toplev, font=font1)
self.button_ok = Button(self.toplev, text="Ok", font=font1,
command=self.get_name)
self.entry_name.pack()
self.button_ok.pack()
def get_name(self):
self.name = self.entry_name.get()
self.toplev.destroy()
class Gui(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.pack()
self.master = master
self.label_text = Label(self, text="Foo Bar Window", font=font1)
self.label_text.pack()
self.button_toplevel = Button(self, text="Create Toplevel",
command=self.get_toplevel, font=font1)
self.button_toplevel.pack()
def get_toplevel(self):
self.my_top = My_Toplevel(self)
if __name__ == "__main__":
root = Tk()
root.title("Parent")
app = Gui(root)
root.mainloop()
You need to pass the data to the Gui instance before you destroy My_Toplevel. One way to do that is to save the name string as an attribute of the Gui instance since you pass that the master parameter when you call My_Toplevel. For example:
from tkinter import *
font1 = font=("Open Sans Standard",16,"bold")
class My_Toplevel():
def __init__(self, master=None):
self.master = master
self.toplev = Toplevel(master)
self.create_widgets()
def create_widgets(self):
self.entry_name = Entry(self.toplev, font=font1)
self.button_ok = Button(self.toplev, text="Ok", font=font1,
command=self.get_name)
self.entry_name.pack()
self.button_ok.pack()
def get_name(self):
self.master.name_data = self.entry_name.get()
self.toplev.destroy()
class Gui(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.pack()
self.master = master
self.label_text = Label(self, text="Foo Bar Window", font=font1)
self.label_text.pack()
self.button_toplevel = Button(self, text="Create Toplevel",
command=self.get_toplevel, font=font1)
self.button_toplevel.pack()
self.name_data = None
Button(self, text="show name", command=self.show_name).pack()
def show_name(self):
print("Name =", self.name_data)
def get_toplevel(self):
self.my_top = My_Toplevel(self)
if __name__ == "__main__":
root = Tk()
root.title("Parent")
app = Gui(root)
root.mainloop()
Press the "show name" button to print the name string to the console.
If you need to save more than a single string, you could append the name to a list, save it in a dictionary, etc.
If you like, you can call the Gui.show_name method just before the TopLevel window is destroyed:
def get_name(self):
self.master.name_data = self.entry_name.get()
self.master.show_name()
self.toplev.destroy()
Hey guys I have to classes that both create a Frame. The first one contains a button that is supposed to close its frame. The second frame simply contains a Label. My code should first create the frame with the button and when the button is pressed the second window should show up. What happens is that when pressing the button a "merged" window is created that contains the button and the label.
import tkinter as tk
class Window1(tk.Frame):
def __init__(self):
tk.Frame.__init__(self)
self.grid()
self.btn = tk.Button(self,text = "button",command = self.run)
self.btn.grid(row = 0,column = 0)
def run(self):
tk.Frame.quit(self)
class Window2(tk.Frame):
def __init__(self):
tk.Frame.__init__(self)
self.grid()
self.label = tk.Label(self,text = "label ")
self.label.grid(row = 0,column = 0)
w = Window1()
w.mainloop()
v = Window2()
v.mainloop()
The first picture is before you press the button, the next one after you pressed the button. The problem seems that tk.Frame.quit(self) doesn't work correctly. I tried similar ways to close the window such as:
tk.Frame.destroy(self)
but that doesn't help either.
edit: I solved it by inheriting the class from tk.TK instead of tk.Frame
Frame doesn't create window - it only group elements. Tk() creates window.
To close window you have to destroy() object create by Tk(). But you don't creat it manually root = tk.Tk() so tkinter create it automatically, but you have no access to this root to close it.
If widget doesn't have parent then it uses root and your Frame does it too.
import tkinter as tk
class Window1(tk.Frame):
def __init__(self, master):
# send `root` to `Frame` as its parent
tk.Frame.__init__(self, master)
# `Frame` will keep `master as `self.master`
# so we don't have to do `self.master = master` manually
self.grid()
self.btn = tk.Button(self, text="Hello Button", command=self.run)
self.btn.grid(row=0, column=0)
def run(self):
# use `master` (`root`) to destroy it
self.master.destroy()
class Window2(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
self.grid()
self.label = tk.Label(self, text="Hello Label")
self.label.grid(row=0, column=0)
root = tk.Tk() # create main window as `root`
Window1(root) # send `root` to `Window1` and later to `Frame`
root.mainloop()
root = tk.Tk()
Window2(root)
root.mainloop()
I want to create some simple tkinter python app (like StickyNotes on Windows), i have create the class mainApplication and i do not know how to by just simply triggering the button create another instance of this class which will be displayed pararell to other window (or even multiple windows). I know how to assigned function to pushButton, and other simple stuff but the problem is with this pararell window displaying. Thanks in advance for help.
class mainApplication(Frame):
_ids = count(0)
def __init__(self, parent):
""" """
self.id = next(self._ids)
Frame.__init__(self, parent)
self.parent = parent
self.parent.minsize(width=200,height=100)
self.parent.geometry(('%dx%d+%d+%d' % (200, 100, 1700, 0+self.id*100)))
self.initUI()
def initUI(self):
""" """
self.parent.title("a2l")
self.pack(fill=BOTH, expand=True)
style = Style()
style.configure("TFrame", background="#333")
frame1 = Frame(self, style="TFrame")
frame1.pack(fill=X)
self.lbl0 = Label(frame1, text="api", width=7, background="#333", foreground = "red")
self.lbl0.pack(side=TOP, padx=5, pady=5)
self.closeButton = Button(self, text="new", command = self.createNewInstance)
self.closeButton.pack(side=RIGHT, padx=5, pady=5)
#=======================================================================
# self.generateButton = Button(self, text="GENERATE", command = self.)
# self.generateButton.pack(side=RIGHT, padx=5, pady=5)
#=======================================================================
def createNewInstance(self):
y = mainApplication()
return y
if __name__ == "__main__":
root = Tk()
x = mainApplication(root).pack(side="top", expand=False)
Tk().mainloop()
You shouldn't create more than one Tk() window in one application with tkinter. Instead tkinter provides a widget called Toplevel which can be useful for this kind of thing.
It creates another window which can exist along side the Tk() window and alongside other Toplevel widgets.
You could use this to create a series of persistent windows with whatever text or widgets you wanted on them at any kind of trigger including a Button.
See my example below for a demonstration:
from tkinter import *
class App:
def __init__(self, root):
self.root = root
self.top = [] #list to contain the Toplevel widgets
self.entry = Entry(self.root)
self.button = Button(self.root, text="Create window", command=self.command)
self.entry.pack()
self.button.pack()
def command(self): #called when button is pressed
self.top.append(Toplevel(self.root)) #adds new Toplevel to the list
Label(self.top[len(self.top)-1], text=self.entry.get()).pack() #Adds label equal to the entry widget to the new toplevel
root = Tk()
App(root)
root.mainloop()
I'm having a trouble when i open a secondary window. Now I'm just creating a toplevel window with a button and I need to open the same secondary window If i click the button (not generate a new instance).
Which is the better way to generate single secondary window and not generating a new window instance?
I leave the code that I'm actually working on:
import tkinter
class LogWindow():
def __init__(self, parent):
self.parent = parent
self.frame = tkinter.Frame(self.parent)
class MainWindow(tkinter.Frame):
def __init__(self, parent):
tkinter.Frame.__init__(self, parent)
self.parent = parent
frame = tkinter.Frame(self, borderwidth=1)
frame.pack(fill=tkinter.BOTH, expand=True, padx=5, pady=5)
self.LogButton = tkinter.Button(frame, text="Log Viewer", command= self.openLogWindow)
self.LogButton.grid(sticky=tkinter.E+tkinter.W)
self.pack(fill=tkinter.BOTH,expand=True)
def openLogWindow(self):
self.logWindow = tkinter.Toplevel(self.parent)
self.app = LogWindow(self.logWindow)
def main():
global app, stopRead
root = tkinter.Tk()
root.geometry("300x300")
app = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()
Maybe i need to have a single instance of a Toplevel class and call show and close to show or hide the secondary window.
Finally after some tests I've found how to solve that, thanks to the #furas response and some investigation about the Tkinter events with the protocol function.
I've got that working with:
import tkinter
logWindowExists = False
class LogWindow():
def __init__(self, parent):
global logWindowExists, root
logWindowExists = True
self.parent = parent
self.frame = tkinter.Frame(self.parent)
def on_closing(self):
global logWindowExists
logWindowExists = False
self.parent.destroy()
class MainWindow(tkinter.Frame):
def __init__(self, parent):
tkinter.Frame.__init__(self, parent)
self.parent = parent
frame = tkinter.Frame(self, borderwidth=1)
frame.pack(fill=tkinter.BOTH, expand=True, padx=5, pady=5)
self.LogButton = tkinter.Button(frame, text="Log Viewer", command= self.openLogWindow)
self.LogButton.grid(sticky=tkinter.E+tkinter.W)
self.pack(fill=tkinter.BOTH,expand=True)
def openLogWindow(self):
if not logWindowExists:
self.logWindow = tkinter.Toplevel(self.parent)
self.app = LogWindow(self.logWindow)
self.logWindow.protocol("WM_DELETE_WINDOW", self.app.on_closing)
else:
self.logWindow.deiconify()
def main():
global app, stopRead, root
root = tkinter.Tk()
root.geometry("300x300")
app = MainWindow(root)
root.mainloop()
if __name__ == '__main__':
main()
Using a boolean to know if the window exists or not i can handle when the window it's opened or not and just show the existing window or creating a new one.
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()