Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ttk tkinter multiple frames/windows

The following application I have created is used to demonstrate multiple windows in tkinter. The main problem is that none of the Entry controls, neither in the bmi-calculator or the converter, accept the values in the entry boxes - they get a ValueError when I do a calculation.

from tkinter import *
from tkinter import ttk
from tkinter import messagebox

class App1(ttk.Frame):
    def createWidgets(self):
        #text variables
        self.i_height = StringVar()
        self.i_weight = StringVar()
        self.o_bmi = StringVar()

        #labels
        self.label1 = ttk.Label(self, text="Enter your weight:").grid(row=0, column=0, sticky=W)
        self.label2 = ttk.Label(self, text="Enter your height:").grid(row=1, column=0, sticky=W)
        self.label3 = ttk.Label(self, text="Your BMI is:").grid(row=2, column=0, sticky=W)

        #text boxes
        self.textbox1 = ttk.Entry(self, textvariable=self.i_weight).grid(row=0, column=1, sticky=E)
        self.textbox2 = ttk.Entry(self, textvariable=self.i_height).grid(row=1, column=1, sticky=E)
        self.textbox3 = ttk.Entry(self, textvariable=self.o_bmi).grid(row=2, column=1, sticky=E)

        #buttons
        self.button1 = ttk.Button(self, text="Cancel/Quit", command=self.quit).grid(row=3, column=1, sticky=E)
        self.button1 = ttk.Button(self, text="Ok", command=self.calculateBmi).grid(row=3, column=2, sticky=E)

    def calculateBmi(self):
        try:
            self.weight = float(self.i_weight.get())
            self.height = float(self.i_height.get())
            self.bmi = self.weight / self.height ** 2.0
            self.o_bmi.set(self.bmi)
        except ValueError:
            messagebox.showinfo("Error", "You can only use numbers.")
        finally:
            self.i_weight.set("")
            self.i_height.set("")

    def __init__(self, master=None):
        ttk.Frame.__init__(self, master)
        self.grid()
        self.createWidgets()

class App2(ttk.Frame):
    def create_widgets(self):
        """Create the widgets for the GUI"""
        #1 textbox (stringvar)
        self.entry= StringVar()
        self.textBox1= ttk.Entry(self, textvariable=self.entry).grid(row=0, column=1)

        #5 labels (3 static, 1 stringvar)
        self.displayLabel1 = ttk.Label(self, text="feet").grid(row=0, column=2, sticky=W)
        self.displayLabel2 = ttk.Label(self, text="is equivalent to:").grid(row=1, column=0)
        self.result= StringVar()
        self.displayLabel3 = ttk.Label(self, textvariable=self.result).grid(row=1, column=1)
        self.displayLabel4 = ttk.Label(self, text="meters").grid(row=1, column=2, sticky=W)

        #2 buttons
        self.quitButton = ttk.Button(self, text="Quit", command=self.quit).grid(row=2, column=1, sticky=(S,E))
        self.calculateButton = ttk.Button(self, text="Calculate", command=self.convert_feet_to_meters).grid(row=2, column=2, sticky=(S,E))

    def convert_feet_to_meters(self):
        """Converts feet to meters, uses string vars and converts them to floats"""
        self.measurement = float(self.entry.get())
        self.meters = self.measurement * 0.3048
        self.result.set(self.meters)

    def __init__(self, master=None):
        ttk.Frame.__init__(self, master)
        self.grid()
        self.create_widgets()

def button1_click():
    root = Tk()
    app = App1(master=root)
    app.mainloop()

def button2_click():
    root = Tk()
    app = App2(master=root)
    app.mainloop()

def main():
    window = Tk()
    button1 = ttk.Button(window, text="bmi calc", command=button1_click).grid(row=0, column=1)
    button2 = ttk.Button(window, text="feet conv", command=button2_click).grid(row=1, column=1)
    window.mainloop()

if __name__ == '__main__':
    main()

How can I fix this, but still maintaining the class structure and the use of python3? BTW - Anything similar to C#'s form1.Show()?

like image 880
py_tk_coder Avatar asked May 17 '11 18:05

py_tk_coder


1 Answers

You have to convert the StringVar() to an integer/float or use IntVar() or DoubleVar()

There are other problems as well. Statements like the following return "None" since it is a grid() object and not a Label() object:

self.label1 = ttk.Label(self, text="Enter your weight:").grid(row=0, column=0, sticky=W)   

I think you will also have problems with two Tk() windows open at the same time. Use Toplevel() or separate frames instead.

like image 159
Joe Avatar answered Sep 24 '22 01:09

Joe