Python Tkinter GUI编程怎么实现Frame切换

wufei123 发布于 2023-05-11 阅读(1523)

1、Frame的tkraise() 方法介绍

通常,一个 Tkinter 应用程序由多个Frame组成。 而且您经常需要在Frame之间切换以显示与用户选择相关的Frame。

Tkinter 允许将Frame堆叠在一起。 要显示特定Frame,只需按堆叠顺序将一个放在另一个之上。 顶部Frame将可见。

要将Frame置于顶部,可以使用 Frame 小部件的 tkraise() 方法,如下所示:

1

frame.tkraise()

2、tkraise用法示例

下面将实现一个温度转换小应用,华氏温度和摄氏温度分别使用两个不同的Frame,UI窗口组成如下:

Python Tkinter GUI编程怎么实现Frame切换

ConverterFrame 将有两个实例,一个将温度从华氏温度转换为摄氏温度,另一个将温度从摄氏温度转换为华氏温度:

Python Tkinter GUI编程怎么实现Frame切换

第一步,定义一个具有两个静态方法的 TemperatureConverter 类:fahrenheit_to_celsius 和 celsius_to_fahrenheit。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

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 更加灵活:

  • 将显示为华氏温度和摄氏度的字符串

  • 用于转换温度的回调函数。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

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 = ''

上面代码如何工作?

  • 1)使用 unit_from 参数显示温度标签。

  • 2)在 convert() 方法中调用 self.convert 回调将温度从一个单位转换为另一个单位。

  • 3)定义 reset() 方法以在Frame从一个切换到另一个时清除条目小部件和结果标签。

第三,定义一个 ControlFrame 类,该类显示用于选择要显示的Frame的单选按钮。 ControFrame 类继承自 ttk.LabelFrame。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

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 类的两个实例,一个负责将温度从华氏温度转换为摄氏温度,另一个负责将温度从摄氏温度转换为华氏温度。 另外,定义一个字典来存储这些Frame。 Frame的键与单选按钮的值相同。

  • 单击单选按钮时,会调用 change_frame() 方法根据所选按钮的值从字典中选择相应的Frame。

  • 调用Frame的 reset() 方法来重置输入字段和结果标签。 并且还调用 tkraise() 方法来显示Frame。

第四,定义从 tk.Tk 类继承的 App 类:

1

2

3

4

5

6

7

class App(tk.Tk):

    def __init__(self):

        super().__init__()

 

        self.title('Temperature Converter')

        self.geometry('300x120')

        self.resizable(False, False)

最后,启动程序

1

2

3

4

if __name__ == "__main__":

    app = App()

    ControlFrame(app)

    app.mainloop()

代码整合如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

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('480x240')

        self.resizable(False, False)

 

 

if __name__ == "__main__":

    app = App()

    ControlFrame(app)

    app.mainloop()

运行结果如下:

Python Tkinter GUI编程怎么实现Frame切换

以上就是Python Tkinter GUI编程怎么实现Frame切换的详细内容


标签:  python 免费教程 

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。