Получение приложения tkinter с несколькими вкладками и кнопками для правильной работы - PullRequest
0 голосов
/ 12 июля 2019

У меня есть небольшое тестовое приложение, использующее Python tkinter, которое я получил на работу. Проблема в том, что он не выходит должным образом при нажатии кнопки «Выйти». Это двухкадровое приложение с вкладками, где я начал с вопроса StackOverflow ttk tkinter несколько кадров / окон .

Теперь это полный пример, который работает, но нуждается в работе, потому что он не завершается и не завершается должным образом. Когда я нажимаю кнопку «Выйти», она убивает фрейм для этой вкладки, но приложение не завершает работу и правильно завершает работу. Я должен нажать на значок «X», чтобы закрыть окно.

Мой главный вопрос: как (и где?) Я могу проверить событие на кнопке «Выйти» на калькуляторе «Футы в метры» или на кнопке «Отмена / Выйти» на калькуляторе ИМТ.

Второй вопрос, который у меня возникает, заключается в том, что дизайн приложения кажется мне неэффективным, поскольку он создает два объекта «Рамка» виджетов, каждый из которых имеет собственный набор кнопок, в том числе 2 кнопки «Выход». Как поместить эти вкладки и фреймы в родительское окно, а затем добавить кнопку выхода в это родительское окно, чтобы закрыть все приложение.

Я изменил кнопки, чтобы должным образом уничтожить фрейм, в котором находится кнопка:

Изменено button2 "command = self.quit" на "command = self.destroy"

self.button2 = ttk.Button (self, text = "Cancel / Quit", command = self.quit) .grid (row = 3, column = 1, sticky = E)

в self.button2 = ttk.Button(self, text="Cancel/Quit", command=self.destroy).grid(row=3, column=1, sticky=E)

""" Created on Thu Jul 11 17:20:22 2019 """

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

class App1(ttk.Frame):
    """ This application calculates BMI and returns a value. """ 

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

    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="Ok", command=self.calculateBmi).grid(row=3, column=2, sticky=E)
## Changed button2 "command=self.quit"  to  "command=self.destroy"
#        self.button2 = ttk.Button(self, text="Cancel/Quit", command=self.quit).grid(row=3, column=1, sticky=E)
        self.button2 = ttk.Button(self, text="Cancel/Quit", command=self.destroy).grid(row=3, column=1, sticky=E)

#exitApplication = tk.Button(root, text='Exit Application', command=root.destroy)
#canvas1.create_window(85, 300, window=exitApplication) 


    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("")

class App2(ttk.Frame):
    """ Application to convert feet to meters or vice versa. """
    def __init__(self, master=None):
        ttk.Frame.__init__(self, master)
        self.grid()
        self.create_widgets()

    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.calculateButton = ttk.Button(self, text="Calculate", command=self.convert_feet_to_meters).grid(row=2, column=2, sticky=(S,E))
        self.quitButton = ttk.Button(self, text="Quit", command=self.destroy).grid(row=2, column=1, sticky=(S,E))

#exitApplication = tk.Button(root, text='Exit Application', command=root.destroy)
#canvas1.create_window(85, 300, window=exitApplication) 


    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)

###  CODE BELOW COMMENTED OUT WHEN JOINING ORIGINAL POSTER CODE WITH HIS SOLUTION
### It seems no longer relevant since App1 and App2 have their own buttons.

#def button1_click():
#    """ This is for the BMI Calculator Widget """
#    root = Tk()
#    app = App1(master=root)
#    app.mainloop()
#
#def button2_click():
#    """ This is for the Feet to Meters Conversion Widget """
#    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()


def main():
    #Setup Tk()
    window = Tk()

    #Setup the notebook (tabs)
    notebook = ttk.Notebook(window)
    frame1 = ttk.Frame(notebook)
    frame2 = ttk.Frame(notebook)
    notebook.add(frame1, text="BMI Calc")
    notebook.add(frame2, text="Feet to Meters")
    notebook.grid()

    #Create tab frames
    app1 = App1(master=frame1)
    app1.grid()
    app2 = App2(master=frame2)
    app2.grid()

    #Main loop
    window.mainloop()

if __name__ == '__main__':
    main()

Приложение не закрывается при нажатии кнопки «Выход». Выходят только отдельные кадры.

1 Ответ

0 голосов
/ 17 июля 2019

Спасибо Мартино за подсказку, которая помогла мне заставить этот пример работать. Я объявил 'window как глобальную переменную, так как она была определена в пространстве имен конструкторов классов. Без этого возникла ошибка неопределенного окна. Этот метод нарушает инкапсуляцию и модульность классов, передавая window как глобальный. Если есть лучший способ сделать это, я хотел бы знать.

    # -*- coding: utf-8 -*-
""" Created on Thu Jul 11 17:20:22 2019   
    Filename: tkinter-multiple-frames-windows_v3.py
    From question on StackOverflow question "ttk tkinter multiple frames/windows"
    at /5614032/ttk-tkinter-neskolko-kadrov-windows
    Now a full example that works but it needed some modification to clarify how it works.
"""

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

class BMICalcApp(ttk.Frame):
    """ This application calculates BMI and returns a value. """ 

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

    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="Ok", command=self.calculateBmi).grid(row=3, column=2, sticky=E)
        self.button2 = ttk.Button(self, text="Cancel/Quit", command=window.destroy).grid(row=3, column=1, 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("")

class ConvertFeetMeters(ttk.Frame):
    """ Application to convert feet to meters or vice versa. """
    def __init__(self, master=None):
        ttk.Frame.__init__(self, master)
        self.grid()
        self.create_widgets()

    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.calculateButton = ttk.Button(self, text="Calculate", command=self.convert_feet_to_meters).grid(row=2, column=2, sticky=(S,E))
        self.quitButton = ttk.Button(self, text="Quit", command=window.destroy).grid(row=2, column=1, 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 main():
    #Setup Tk()
    global window 
    window = Tk()

    #Setup the notebook (tabs)
    notebook = ttk.Notebook(window)
    frame1 = ttk.Frame(notebook)
    frame2 = ttk.Frame(notebook)
    notebook.add(frame1, text="BMI Calc")
    notebook.add(frame2, text="Feet to Meters")
    notebook.grid()

    #Create tab frames
    bmi_calc = BMICalcApp(master=frame1)
    bmi_calc.grid()
    feet_meters_calc = ConvertFeetMeters(master=frame2)
    feet_meters_calc.grid()

    #Main loop
    window.mainloop()

if __name__ == '__main__':
    main()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...