I am currently trying to create two windows with a tkinter program but it doesn't seem to be working. It was only recently that i just moved over my game to tkinter and it is the first time working with tkinter. Due to that I have no clue why this isn't working.
This is my first window and its working fine
class Application(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
self.create_widgets()
self.crafting_listbox
My second window though isn't working
class Application_2(tk.Frame):
def __init__(self, master=None):
super().__init__(master)
self.pack()
self.crafting_listbox()
Then the finishing bit
root = tk.Tk()
app = Application(master=root)
app.mainloop()
I am unsure why this isn't working, whats going wrong?
You never call your second Frame.
To make a second window use the Toplevel class.
root = tk.Tk()
app = Application(master=root)
second_win = tk.Toplevel(root)
app2 = Application_2(second_win)
root.mainloop()
Related
I have programmed a 2600 lines application which worked great when running from the IDE. Now I have created an executable via Pyinstaller and now the GUI does not start. The application starts and disappears quickly. I do not get any errors (anymore, solved them), however this problem remains. I think it has to do with missing the mainloop() in my application, which I don't know how to apply in this particular case. Usually its like this:
root = tk.Tk()
root.mainloop()
In my case I created a class for my window adding a menubar and label as statusbar (the latter not shown in my code below). This makes me assigning this class being a Tk() to main_window. Where do I put the mainloop() without getting an error?
I already tried:
main_window.mainloop()
since main_window is the window where all frames put on to, but then I get the following error in the IDE:
main_window.mainloop() AttributeError: 'AppWindow' object has no attribute 'mainloop'
How do I apply the mainloop() into my application without getting the above mentioned error? Or how do I get my GUI to be working in a different manner? Both answers are welcome.
Here is the necessary code to know:
import tkinter as tk
class AppWindow():
def __init__(self, master):
self.master = master
master.title("Basic Application")
master.geometry("1060x680")
master.grid_propagate(False)
#create drop down menu
self.menubar = tk.Menu(master) # main menubar
#Add filemenu
self.filemenu = tk.Menu(self.menubar, tearoff=0) #sub menu
self.filemenu.add_separator() #create a bar in the menu
self.filemenu.add_command(label="Quit", command=master.destroy) #Add submenu item
self.menubar.add_cascade(label="File", menu=self.filemenu) #Add submenu to menubar
self.master.config(menu=self.menubar) #Show menu
class FrameOne(tk.Frame):
def __init__(self, parent):
super().__init__()
self["borderwidth"]=5
self["relief"]="ridge"
self.create_widgets() #Function which creates all widgets
self.position_widgets() #Function which position all widgets
def create_widgets(self): #Function which creates all widgets
pass
def position_widgets(self): #Function which position all widgets
pass
#Create a window as defined in the AppWindow class
main_window = AppWindow(tk.Tk())
#Create a Frame as defined in class FrameOne
first_frame = FrameOne(main_window)
first_frame.grid(row=0, column=0) #Positioning Frame on Window
main_window.mainloop() #THIS PROVIDES AN ERROR | GUI DOES NOT START WITHOUT
mainloop is a method on the tkinter root window and on tkinter itself. Like the error says, it's not a method of your AppWindow class.
In your case you should do it like this:
root = tk.Tk()
main_window = AppWindow(root)
root.mainloop()
I am working on code in tkinter python v3.7 where I want to open a new window which has same functionalities like original window. How can I do that?
While searching for solution I came across function naming Toplevel which creates new tkinter window. But this new window is completely new, It doesn't have functionalities(Button, geometry size in my case) which were provided in original one.
from tkinter import *
class TextPad:
def new_window(self):
top = Toplevel()
def __init__(self, master):
master.title('Text Pad')
master.geometry('400x400')
self.button = Button(master, text='Press',
command=self.new_window)
self.button.pack()
root = Tk()
t = TextPad(root)
root.mainloop()
My original window has geometry size of '400x400' and It has 'button', I want to open a new window having this functionalities.
I assume you want two (or more) windows at the same time.
If you want identical window then use again TextPad()
but this time use Toplevel() instead of Tk()
def new_window(self):
top = TextPad(Toplevel())
and don't run second mainloop()
If you want replace first window by new window - to have alwasy only one window - then you would have to destroy old window and then create new one using TextPad() with Tk() and mainloop()
But it would need to use self.master instead of master to have access to master in method new_window
from tkinter import *
class TextPad:
def new_window(self):
self.master.destroy()
root = Tk()
t = TextPad(root)
root.mainloop()
def __init__(self, master):
self.master = master
self.master.title('Text Pad')
self.master.geometry('400x400')
self.button = Button(self.master, text='Press',
command=self.new_window)
self.button.pack()
root = Tk()
t = TextPad(root)
root.mainloop()
I am watching Sentdex's Tkinter tutorial and there are some related problems that arise:
Basic Class Questions that I'm just new to: How come Frame follows after the declaration of the Window class (sorry for a basic class question)? How is self.pack working without specifying what to pack?
What does frame.__init__ contribute to this code?
The code is this:
from tkinter import *
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master, bg='LightBlue')
self.master = master
self.init_window()
def init_window(self):
self.master.title("GUI")
self.master.geometry('400x400')
self.pack(fill=BOTH, expand=1)
quitButton = Button(self, text='Quit')
quitButton.place(x=0, y=0)
root = Tk()
app = Window(root)
root.mainloop()
Thanks in advance!
The class Window inherits from tk.Frame, this is what (Frame) after Window means.
In such a situation, Window is also a tk.Frame, hence when calling pack() on self, it is in essence packing itself.
It is likely less confusing to avoid star imports:
import tkinter as tk
class Window(tk.Frame): # <-- avoid star imports
def __init__(self, master=None):
self.master = master
super().__init__(master, bg='LightBlue') # <-- use super instead of hardcoding the parent class
self.init_window()
def init_window(self):
self.master.title("GUI")
self.master.geometry('400x400')
self.pack(fill=tk.BOTH, expand=True)
self.quit_button = tk.Button(self, text='Quit',
command=self.master.destroy)
self.quit_button.pack()
if __name__ == '__main__':
root = tk.Tk()
app = Window(root)
root.mainloop()
Frame is in brackets so that the class Window can inherit the methods of the tkinter.Frame class.
The Frame.init function initialises the class as a tkinter Frame.
The self.pack() line packs the Frame into self.master, which was created a couple of lines before.
Have a look at some basic classes and build up from there.
I did this tutorial a little while ago and found that I had to spend a little time having a look at classes first. I used some youtube videos I think, good luck!
I am writing a multi-window GUI program in tkinter. The code shown below is the layout of the main part of my code. The first window works fine but when I get to the second window by calling self.next_win, some things start to go sightly funny.
The main issue is when I go to destroy the GUI: I want there to be a quit button in each window which, when pushed, closes the entire GUI (root.destroy). From the first window this works fine, I call the self.quit method; but when I get to the second window it doesn't work. I know this is because master in the second window is a Toplevel widget but I'm not sure how to get around this. I don't see how I can call root.destroy from the second window.
How can I fix this? A line in the SecondWin.quit method perhaps, or a better code structure which makes the solution trivial (bear in mind I am a beginner so trivialities will have to be explained)? Thanks.
class FirstWin:
def __init__(self, master):
self.master = master
...
...
def next_win(self):
self.master.withdraw()
root2 = Toplevel()
SecondWin(root2)
def quit(self):
self.master.destroy()
class SecondWin:
def __init__(self, master):
self.master = master
...
...
def quit(self):
self.master.destroy() # What goes in here?
...
def main():
root = Tk()
GUI = FirstWin(root)
root.mainloop()
if __name__ == '__main__':
main()
All you need to do is tell SecondWin what the root window is, and it can destroy it.
...
root2 = Toplevel()
# tell the second window what the master is,
# and also tell it to be a child of FirstWin.
SecondWin(self.master, root2)
...
class SecondWin():
def __init__(self, root, master):
# root is the root window, master is the parent of this window
self.root = root
self.master = master
<other initialization code here>
def quit(self):
self.root.destroy()
I'm trying to make a GUI using Tkinter and have come to implementing a menu bar. I've looked at a few tutorials and written some code for it, but a menu bar never seems to appear - just a blank frame with a white background. This doesn't just happen for my code though; on copying and pasting the code of one of the aforementioned tutorials into a new script, the same behaviour is exhibited.
I'd appreciate it if anyone could shed any light on what's causing this. My system is OS X 10.5, Python 2.7, Tk 8.4. Here's the code from the tutorial that doesn't appear to work:
#!/usr/local/bin/python2.7
from Tkinter import *
from ttk import *
class App(Frame):
def __init__(self):
Frame.__init__(self)
self.master.geometry('400x300')
self.master.title(__file__)
self.pack()
self.menu = Menu(tearoff=False)
self.master.config(menu = self.menu)
fm = self.file_menu = None
fm = Menu(self.menu, tearoff=False)
self.menu.add_cascade(label='File', menu = fm)
fm.add_command(label='Say Hello', command = self.say_hello)
fm.add_separator()
fm.add_command(label='Quit', command = self.quit)
self.mainloop()
def say_hello(self, *e):
self.label = Label(self.master, text='Hello there!')
self.label.pack(anchor=CENTER, fill=NONE, expand=YES, side=LEFT)
if __name__ == '__main__':
App()
and my code is here:
from Tkinter import *
class App(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
parent.title("Cluedo Solver 1.0")
menubar = Menu(root)
menubar.add_command(label="File")
menubar.add_command(label="Quit", command=root.quit())
root.config(menu=menubar)
root=Tk()
root.geometry("300x250+300+300")
app=App(root)
root.mainloop()
Based on some comments you made to one of the answers, you are apparently running this on a Macintosh. The code works fine, but the menu appears in the mac menubar rather than on the window like it does on Windows and Linux. So, there's nothing wrong with your code as far as the menubar is concerned.
Code with Explanation
From personal experience, I have found that it is usually easier to manage all widgets in a widgets method. That is what I did here, and it worked. Also, instead of parent, I used master. I will now walk you through the code step-by-step.
from Tkinter import *
We import Tkinter (GUI stuff)
class App(Frame):
We create a class called App, which is the Frame where widgets are held.
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.widgets()
We create a method called __init__. This initializes the class, and runs another method called widgets.
def widgets(self):
menubar = Menu(root)
menubar.add_command(label="File")
menubar.add_command(label="Quit", command=root.quit())
root.config(menu=menubar)
We create the widgets method. This is where the widget, menubar is added. If we were to create anymore widgets, they would also be here.
root=Tk()
root.title("Menubar")
app=App(root)
root.mainloop()
Lastly, we give the entire window some properties. We give it a title, Menubar, and run the App class. lastly, we start the GUI's mainloop with root.mainloop.
I am trying the code as above, but all I get is "Python" on the macOS menubar and it's usual pulldown. tkinter just doesn't seem to work menus on macOS 10.14.1
I think what is happening is that there are mac specific fixups that are changing the event codes so certain menu items will end up under the Python menu item instead of where expected, I saw some of this in my own experiments. When I expanded my code and used some of the reserved FILE event codes instead of the standard ones, things worked better.
#!/Library/Frameworks/Python.framework/Versions/3.7/bin/python3.7
# -*- coding: utf-8 -*-# -*- coding: utf-8 -*-
from tkinter import *
class App(Frame):
def __init__(self, master):
Frame.__init__(self, master)
self.grid()
self.widgets()
def widgets(self):
menubar = Menu(root)
menubar.add_command(label = 'File')
menubar.add_command(label = 'quit', command = root.quit())
root.config(menu = menubar)
root = Tk()
root.title('Menubar')
app = App(root)
root.mainloop()
Check your mac menu bar if you are doing any GUI that involves menubar which you will like to view or test. Its subtle and you may think you code is not to working. Click on the app(in this case python window), it will show a drop down menubar.
guys to solve the problem
look the file part that's where the menubar for mac is located