Switching between Frames Using the Frame tkraise() Method

2024. 3. 16. 20:58GUI/tkinter

요약:이 튜토리얼에서는 Tkinter 애플리케이션에서 프레임 사이를 전환하기 위해 Frame tkraise() 메소드를 사용하는 방법을 배우게 됩니다.

Frame tkraise() 메소드 소개

일반적으로 Tkinter 애플리케이션은 여러 개의 프레임 으로 구성됩니다. 그리고 사용자의 선택과 관련된 프레임을 표시하기 위해 프레임 간에 전환해야 하는 경우도 많습니다.

Tkinter를 사용하면 프레임을 서로 쌓을 수 있습니다. 특정 프레임을 표시하려면 쌓인 순서에서 한 프레임을 다른 프레임 위에 올리기만 하면 됩니다. 상단 프레임이 표시됩니다.

프레임을 맨 위로 가져오려면, 다음과 같이 Frame 위젯의 tkraise() 메서드를 사용합니다.

frame.tkraise()

Frame tkraise() 메소드 예제

이 예에서는 섭씨에서 화씨로의 온도 변환을 추가하여 온도 변환기 애플리케이션을 확장합니다.

 

 

기본적으로 애플리케이션은 온도를 화씨에서 섭씨로 변환합니다.

 

 

C 에서 F 라디오 버튼을 선택하면, 애플리케이션에 온도를 섭씨에서 화씨로 변환할 수 있는 새 프레임이 표시됩니다.

 

 

이 애플리케이션을 빌드하려면 세 가지 주요 위젯이 필요합니다.

  • 루트 창.
  • 양식 필드를 보여주는 ConverterFrame입니다.
  • 그리고 라디오 버튼이 보여주는 ControlFrame입니다.

 

여기에 ConverterFrame는 두 개의 인스턴스가 있습니다. 하나는 온도를 화씨에서 섭씨로 변환하고, 다른 하나는 온도를 섭씨에서 화씨로 변환합니다.

 

 

먼저 두 개의 정적 메서드 fahrenheit_to_celsius 및 celsius_to_fahrenheit가 있는 TemperatureConverter 클래스를 정의합니다.

class TemperatureConverter:
    @staticmethod
    def fahrenheit_to_celsius(f, format=True):
        result = (f - 32) * 5/9
        if format:
            return f'{f} Fahrenheit = {result:.2f} Celsius'
        return result

    @staticmethod
    def celsius_to_fahrenheit(c, format=True):
        result = c * 9/5 + 32
        if format:
            return f'{c} Celsius = {result:.2f} Fahrenheit'
        return result

두 번째 인수를 무시하거나 True를 전달하는 경우 fahrenheit_to_celsius 및 celsius_to_fahrenheit 메서드는 형식화된 문자열을 반환합니다. 그렇지 않으면 결과를 숫자로 반환합니다.

둘째, 온도를 화씨에서 섭씨로 또는 그 반대로 변환하기 위한 UI를 표시하는 ConverterFrame를 정의합니다.

이를 수행하려면 __init__() 메소드에 다음 매개변수를 추가하여 ConverterFrame을 더욱 유연하게 만들어야 합니다.

  • 화씨와 섭씨로 표시되는 문자열
  • 온도 변환을 위한 콜백 함수입니다.

다음은 전체 ConverterFrame클래스를 보여줍니다.

In [5]:
import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showerror
  • 에러를 줄이기 위하여 먼저 import 문을 사용하였습니다.
In [7]:
class ConverterFrame(ttk.Frame):
    def __init__(self, container, unit_from, converter):
        super().__init__(container)

        self.unit_from = unit_from
        self.converter = converter

        # field options
        options = {'padx': 5, 'pady': 0}

        # temperature label
        self.temperature_label = ttk.Label(self, text=self.unit_from)
        self.temperature_label.grid(column=0, row=0, sticky='w',  **options)

        # temperature entry
        self.temperature = tk.StringVar()
        self.temperature_entry = ttk.Entry(self, textvariable=self.temperature)
        self.temperature_entry.grid(column=1, row=0, sticky='w', **options)
        self.temperature_entry.focus()

        # button
        self.convert_button = ttk.Button(self, text='Convert')
        self.convert_button.grid(column=2, row=0, sticky='w', **options)
        self.convert_button.configure(command=self.convert)

        # result label
        self.result_label = ttk.Label(self)
        self.result_label.grid(row=1, columnspan=3, **options)

        # add padding to the frame and show it
        self.grid(column=0, row=0, padx=5, pady=5, sticky="nsew")

    def convert(self, event=None):
        """  Handle button click event
        """
        try:
            input_value = float(self.temperature.get())
            result = self.converter(input_value)
            self.result_label.config(text=result)
        except ValueError as error:
            showerror(title='Error', message=error)

    def reset(self):
        self.temperature_entry.delete(0, "end")
        self.result_label.text = ''

동작 방식.

  • 온도에 대한 레이블을 표시하려면 unit_from 인수를 사용하십시오 .
  • 온도를 한 단위에서 다른 단위로 변환하려면 convert() 메서드에서 self.convert 콜백을 호출하세요.
  • 프레임이 전환될 때 항목 위젯과 결과 라벨을 지우는 reset() 메서드를 정의합니다 . 셋째, 표시할 프레임을 선택하기 위한 라디오 버튼을 표시하는 ControlFrame 클래스를 정의합니다. ControFrame 클래스는 ttk.LabelFrame에서 상속됩니다.
In [8]:
class ControlFrame(ttk.LabelFrame):
    def __init__(self, container):

        super().__init__(container)
        self['text'] = 'Options'

        # radio buttons
        self.selected_value = tk.IntVar()

        ttk.Radiobutton(
            self,
            text='F to C',
            value=0,
            variable=self.selected_value,
            command=self.change_frame).grid(column=0, row=0, padx=5, pady=5)

        ttk.Radiobutton(
            self,
            text='C to F',
            value=1,
            variable=self.selected_value,
            command=self.change_frame).grid(column=1, row=0, padx=5, pady=5)

        self.grid(column=0, row=1, padx=5, pady=5, sticky='ew')

        # initialize frames
        self.frames = {}
        self.frames[0] = ConverterFrame(
            container,
            'Fahrenheit',
            TemperatureConverter.fahrenheit_to_celsius)
        self.frames[1] = ConverterFrame(
            container,
            'Celsius',
            TemperatureConverter.celsius_to_fahrenheit)

        self.change_frame()

    def change_frame(self):
        frame = self.frames[self.selected_value.get()]
        frame.reset()
        frame.tkraise()

동작 방식.

  • 각 라디오 버튼에는 0 또는 1의 값이 있습니다.
  • ConverterFrame 클래스에서 두 개의 인스턴스를 만듭니다. 하나는 화씨에서 섭씨로 온도를 변환하고, 다른 하나는 온도를 섭씨에서 화씨로 변환합니다. 또한 이러한 프레임을 저장할 사전을 정의하십시오. 프레임의 키는 라디오 버튼의 값과 동일합니다.
  • 라디오 버튼을 클릭하면, 선택한 버튼의 값에 따라 사전에서 해당 프레임을 선택하는 change_frame() 메서드가 호출됩니다.
  • 입력 필드와 결과 레이블을 재설정하려면 프레임의 reset() 메소드를 호출하십시오. 또한 프레임을 표시하는 tkraise() 메서드를 호출합니다.

넷째, tk.Tk 클래스에서 하위 클래스를 만드는 App 클래스를 정의합니다.

In [9]:
class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title('Temperature Converter')
        self.geometry('300x120')
        self.resizable(False, False)

마지막으로 if name == "main" 블록에서 애플리케이션을 부트스트랩합니다.

In [10]:
if __name__ == "__main__":
    app = App()
    ControlFrame(app)
    app.mainloop()

모두 함께 모으면 아래와 같습니다.

In [11]:
import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showerror


class TemperatureConverter:
    @staticmethod
    def fahrenheit_to_celsius(f, format=True):
        result = (f - 32) * 5/9
        if format:
            return f'{f} Fahrenheit = {result:.2f} Celsius'
        return result

    @staticmethod
    def celsius_to_fahrenheit(c, format=True):
        result = c * 9/5 + 32
        if format:
            return f'{c} Celsius = {result:.2f} Fahrenheit'
        return result


class ConverterFrame(ttk.Frame):
    def __init__(self, container, unit_from, converter):
        super().__init__(container)

        self.unit_from = unit_from
        self.converter = converter

        # field options
        options = {'padx': 5, 'pady': 0}

        # temperature label
        self.temperature_label = ttk.Label(self, text=self.unit_from)
        self.temperature_label.grid(column=0, row=0, sticky='w',  **options)

        # temperature entry
        self.temperature = tk.StringVar()
        self.temperature_entry = ttk.Entry(self, textvariable=self.temperature)
        self.temperature_entry.grid(column=1, row=0, sticky='w', **options)
        self.temperature_entry.focus()

        # button
        self.convert_button = ttk.Button(self, text='Convert')
        self.convert_button.grid(column=2, row=0, sticky='w', **options)
        self.convert_button.configure(command=self.convert)

        # result label
        self.result_label = ttk.Label(self)
        self.result_label.grid(row=1, columnspan=3, **options)

        # add padding to the frame and show it
        self.grid(column=0, row=0, padx=5, pady=5, sticky="nsew")

    def convert(self, event=None):
        """  Handle button click event
        """
        try:
            input_value = float(self.temperature.get())
            result = self.converter(input_value)
            self.result_label.config(text=result)
        except ValueError as error:
            showerror(title='Error', message=error)

    def reset(self):
        self.temperature_entry.delete(0, "end")
        self.result_label.text = ''


class ControlFrame(ttk.LabelFrame):
    def __init__(self, container):

        super().__init__(container)
        self['text'] = 'Options'

        # radio buttons
        self.selected_value = tk.IntVar()

        ttk.Radiobutton(
            self,
            text='F to C',
            value=0,
            variable=self.selected_value,
            command=self.change_frame).grid(column=0, row=0, padx=5, pady=5)

        ttk.Radiobutton(
            self,
            text='C to F',
            value=1,
            variable=self.selected_value,
            command=self.change_frame).grid(column=1, row=0, padx=5, pady=5)

        self.grid(column=0, row=1, padx=5, pady=5, sticky='ew')

        # initialize frames
        self.frames = {}
        self.frames[0] = ConverterFrame(
            container,
            'Fahrenheit',
            TemperatureConverter.fahrenheit_to_celsius)
        self.frames[1] = ConverterFrame(
            container,
            'Celsius',
            TemperatureConverter.celsius_to_fahrenheit)

        self.change_frame()

    def change_frame(self):
        frame = self.frames[self.selected_value.get()]
        frame.reset()
        frame.tkraise()


class App(tk.Tk):
    def __init__(self):
        super().__init__()

        self.title('Temperature Converter')
        self.geometry('300x120')
        self.resizable(False, False)


if __name__ == "__main__":
    app = App()
    ControlFrame(app)
    app.mainloop()

요약

  • 프레임 목록의 맨 위에 프레임을 가져오려면 tkraise() 메소드를 사용하십시오 .

 

'GUI > tkinter' 카테고리의 다른 글

Tkinter askyesno  (0) 2024.03.18
Tkinter messagebox  (0) 2024.03.17
Developing a Full Tkinter Object-Oriented Application  (0) 2024.03.15
Tkinter Object-Oriented Frames  (0) 2024.03.14
Tkinter Object-Oriented Window  (0) 2024.03.13