Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tkinter example code for multiple windows, why won't buttons load correctly?

I am writing a program which should:

  1. Open a window with the press of a button.
  2. Close the newly opened window with the press of another button.

I'm using classes so I can insert the code into a larger program later. However, I can't get my buttons to load correctly.

import tkinter as tk

class Demo1(tk.Frame):
    def __init__(self):
        tk.Frame.__init__(self)
        self.pack()
        self.master.title("Demo 1")
        self.button1 = tk.Button(self, text = "Button 1", width = 25,
                               command = self.new_window)
        self.button1.grid(row = 0, column = 1, columnspan = 2, sticky = tk.W+tk.E+tk.N+tk.S)

    def new_window(self):
        self.newWindow = Demo2()

class Demo2(tk.Frame):
    def __init__(self):
        new = tk.Frame.__init__(self)
        new = tk.Toplevel(self)
        new.title("Demo 2")
        new.button = tk.Button(text = "Button 2", width = 25,
                               command = self.close_window)
        new.button.pack()

    def close_window(self):
        self.destroy()

def main():
    Demo1().mainloop()

if __name__ == '__main__':
    main()
like image 892
ADB Avatar asked Apr 20 '13 00:04

ADB


People also ask

Can you have multiple windows in Tkinter?

Unlike the main window, you can create as many top-level windows as you want. The moment you create the Toplevel window, it'll display on the screen. Second, add widgets to the Toplevel window like you do with the frames and main window.

How do I switch between Tkinter windows?

One way to switch frames in tkinter is to destroy the old frame then replace it with your new frame. I have modified Bryan Oakley's answer to destroy the old frame before replacing it. As an added bonus, this eliminates the need for a container object and allows you to use any generic Frame class.


4 Answers

I rewrote your code in a more organized, better-practiced way:

import tkinter as tk  class Demo1:     def __init__(self, master):         self.master = master         self.frame = tk.Frame(self.master)         self.button1 = tk.Button(self.frame, text = 'New Window', width = 25, command = self.new_window)         self.button1.pack()         self.frame.pack()      def new_window(self):         self.newWindow = tk.Toplevel(self.master)         self.app = Demo2(self.newWindow)  class Demo2:     def __init__(self, master):         self.master = master         self.frame = tk.Frame(self.master)         self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)         self.quitButton.pack()         self.frame.pack()      def close_windows(self):         self.master.destroy()  def main():      root = tk.Tk()     app = Demo1(root)     root.mainloop()  if __name__ == '__main__':     main() 

Result:

Demo1 window Demo2 window

like image 115
Rushy Panchal Avatar answered Oct 05 '22 13:10

Rushy Panchal


You need to specify the master for the second button. Otherwise it will get packed onto the first window. This is needed not only for Button, but also for other widgets and non-gui objects such as StringVar.

Quick fix: add the frame new as the first argument to your Button in Demo2.

Possibly better: Currently you have Demo2 inheriting from tk.Frame but I think this makes more sense if you change Demo2 to be something like this,

class Demo2(tk.Toplevel):          def __init__(self):         tk.Toplevel.__init__(self)         self.title("Demo 2")         self.button = tk.Button(self, text="Button 2", # specified self as master                                 width=25, command=self.close_window)         self.button.pack()      def close_window(self):         self.destroy() 

Just as a suggestion, you should only import tkinter once. Pick one of your first two import statements.

like image 37
Jared Avatar answered Oct 05 '22 13:10

Jared


#!/usr/bin/env python
import Tkinter as tk

from Tkinter import *

class windowclass():

        def __init__(self,master):
                self.master = master
                self.frame = tk.Frame(master)
                self.lbl = Label(master , text = "Label")
                self.lbl.pack()
                self.btn = Button(master , text = "Button" , command = self.command )
                self.btn.pack()
                self.frame.pack()

        def command(self):
                print 'Button is pressed!'

                self.newWindow = tk.Toplevel(self.master)
                self.app = windowclass1(self.newWindow)

class windowclass1():

        def __init__(self , master):
                self.master = master
                self.frame = tk.Frame(master)
                master.title("a")
                self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25 , command = self.close_window)
                self.quitButton.pack()
                self.frame.pack()


        def close_window(self):
                self.master.destroy()


root = Tk()

root.title("window")

root.geometry("350x50")

cls = windowclass(root)

root.mainloop()
like image 35
Sumanta Avatar answered Oct 05 '22 14:10

Sumanta


I tried to use more than two windows using the Rushy Panchal example above. The intent was to have the change to call more windows with different widgets in them. The butnew function creates different buttons to open different windows. You pass as argument the name of the class containing the window (the second argument is nt necessary, I put it there just to test a possible use. It could be interesting to inherit from another window the widgets in common.

import tkinter as tk

class Demo1:
    def __init__(self, master):
        self.master = master
        self.master.geometry("400x400")
        self.frame = tk.Frame(self.master)
        self.butnew("Window 1", "ONE", Demo2)
        self.butnew("Window 2", "TWO", Demo3)
        self.frame.pack()

    def butnew(self, text, number, _class):
        tk.Button(self.frame, text = text, width = 25, command = lambda: self.new_window(number, _class)).pack()

    def new_window(self, number, _class):
        self.newWindow = tk.Toplevel(self.master)
        _class(self.newWindow, number)


class Demo2:
    def __init__(self, master, number):
        self.master = master
        self.master.geometry("400x400+400+400")
        self.frame = tk.Frame(self.master)
        self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
        self.label = tk.Label(master, text=f"this is window number {number}")
        self.label.pack()
        self.quitButton.pack()
        self.frame.pack()

    def close_windows(self):
        self.master.destroy()

class Demo3:
    def __init__(self, master, number):
        self.master = master
        self.master.geometry("400x400+400+400")
        self.frame = tk.Frame(self.master)
        self.quitButton = tk.Button(self.frame, text = 'Quit', width = 25, command = self.close_windows)
        self.label = tk.Label(master, text=f"this is window number {number}")
        self.label.pack()
        self.label2 = tk.Label(master, text="THIS IS HERE TO DIFFERENTIATE THIS WINDOW")
        self.label2.pack()
        self.quitButton.pack()
        self.frame.pack()

    def close_windows(self):
        self.master.destroy()




def main(): 
    root = tk.Tk()
    app = Demo1(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Open the new window only once

To avoid having the chance to press multiple times the button having multiple windows... that are the same window, I made this script (take a look at this page too)

import tkinter as tk


def new_window1():
    global win1
    try:
        if win1.state() == "normal": win1.focus()
    except:
        win1 = tk.Toplevel()
        win1.geometry("300x300+500+200")
        win1["bg"] = "navy"
        lb = tk.Label(win1, text="Hello")
        lb.pack()


win = tk.Tk()
win.geometry("200x200+200+100")
button = tk.Button(win, text="Open new Window")
button['command'] = new_window1
button.pack()
win.mainloop()
like image 33
PythonProgrammi Avatar answered Oct 05 '22 12:10

PythonProgrammi