55
1 of 43 8 8 第 第第第第第第 第 第第第第第第 第第第第 第第 2014. 5. 20 第第第第第第第 -Python 第第

第 8 讲 图形用户界面

  • Upload
    aysel

  • View
    102

  • Download
    7

Embed Size (px)

DESCRIPTION

计算机编程导论 - Python 语言. 第 8 讲 图形用户界面. 讲课教师:常姗 2014. 5. 20. 程序的用户界面. 程序中与用户进行交互的部分 用户通过 UI 向程序输入数据或者请求程序执行特定任务 程序通过 UI 向用户显示各种信息 UI 应该是 用户友好的 两类 UI 命令行界面 图形界面( GUI). GUI 构件 / 控件 / 组件. 窗口 Window 是容器:可以 容纳其他构件 的构件 常用操作:移动,改变大小等 程序有一个根窗口 标签 Label 按钮 Button 菜单 Menu 框架 Frame :分隔窗口空间 - PowerPoint PPT Presentation

Citation preview

Page 1: 第 8 讲 图形用户界面

1 of 43

第第 88 讲 图形用户界面讲 图形用户界面

讲课教师:常姗 2014. 5. 20

计算机编程导论-Python 语言

Page 2: 第 8 讲 图形用户界面

2 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

程序中与用户进行交互的部分 用户通过 UI 向程序输入数据或者请求程序执行特定任务 程序通过 UI 向用户显示各种信息

UI 应该是用户友好的两类 UI

命令行界面 图形界面 (GUI)

程序的用户界面程序的用户界面

Page 3: 第 8 讲 图形用户界面

3 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

窗口 Window 是容器 : 可以容纳其他构件容纳其他构件的构件

常用操作:移动,改变大小等 程序有一个根窗口

标签 Label按钮 Button菜单 Menu框架 Frame :分隔窗口空间

也是容器

GUIGUI 构件构件 // 控件控件 // 组件组件

OK Cancel

勾选钮C1

框架F1

窗口W

框架F2

勾选钮C2

OK Cancel

勾选钮C1

框架F1

窗口W

框架F2

勾选钮C2

基本界面元素

Page 4: 第 8 讲 图形用户界面

4 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

父子关系 在一个构件内创建另一个构件 界面上全体构件形成一个层次结构 顶层是根窗口

设计图形界面,需要指明构件间的父子关系

父构件内安排子构件:使用布局管理器

构件之间的关系构件之间的关系

Page 5: 第 8 讲 图形用户界面

5 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

GUI 程序的执行流程取决于与用户的实时交互用户的实时交互

事件驱动编程 普通程序的执行 : 启动——做事——终止 事件驱动程序的执行 : 启动——事件循环

等待事件发生 , 然后处理程序的终止也是由特定事件 ( 如关闭窗口事件 ) 引起的

事件驱动事件驱动

Page 6: 第 8 讲 图形用户界面

6 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

事件 : 例如点击鼠标 , 按下键盘等 .事件处理程序 : 对事件进行处理的代码 . 事件驱动编程 : 一种编程范型

程序有一个事件循环,循环的做两件事:事件监测

OS 功能 , 由工具包提供支持事件处理

应用程序员只需编写自己的事件处理程序

基本概念基本概念

Page 7: 第 8 讲 图形用户界面

7 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

需要 GUI 工具包 将低层细节对程序员隐藏 跨平台 Python 标准库 :Tkinter

GUI 编程 设计界面外观 为每个构件定义事件处理代码 建立启动初始化和总控部分

GUIGUI 编程编程

Page 8: 第 8 讲 图形用户界面

8 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

TkinterTkinter 的常用构件类的常用构件类ButtonCanvasCheckbuttonEntryFrameLabelListboxMenuMessageRadiobuttonTextToplevel

Page 9: 第 8 讲 图形用户界面

9 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

导入 Tkinter建立根窗口进入事件循环例 :eg8_1.pyfrom Tkinter import *root = Tk()root.mainloop()

最简单的最简单的 TkinterTkinter 程序程序

Page 10: 第 8 讲 图形用户界面

10 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

两步 : 创建 布局

例 :eg8_2.py

from Tkinter import *root = Tk()aLabel = Label(root,text="Hello World")aLabel.pack()root.mainloop()

在窗口中添加构件在窗口中添加构件

Page 11: 第 8 讲 图形用户界面

11 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

构件对象有很多属性 ( 实例变量 ): 创建时设置属性的值

属性一般都有缺省值用“关键字参数 " 方式设置较方便 : 属性 = 属性值

创建时不设置 , 将来再设置或修改利用构件类的 config 方法 :对象 .config( 属性 = 属性值 )对象视为字典 :对象 [ 属性 ]= 属性值

在窗口中添加构件在窗口中添加构件

Page 12: 第 8 讲 图形用户界面

12 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

根窗口的标题设置root.title("My GUI") 缺省值为 "Tk"

根窗口的尺寸设置root.geometry("400x400") 缺省值为 200x200

根窗口根窗口

Page 13: 第 8 讲 图形用户界面

13 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

GUI 中的所有构件按父子关系构成树状层次结构树状层次结构每个构件都有 master 和 children 属性

Tkinter 自动维护这两个属性的值 编程时可利用这两个属性 , 例如 :aLabel.master.title("My GUI")

构件间的父子关系构件间的父子关系

Page 14: 第 8 讲 图形用户界面

14 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

根据需要创建多个构件 , 然后在窗口中进行布局 .例 :eg8_3.py

from Tkinter import *

root = Tk()

aLabel = Label(root,text="Hello World")

aLabel.pack()

aButton = Button(root,text="Click Me")

aButton.pack()

root.mainloop()

界面设计过程界面设计过程

Page 15: 第 8 讲 图形用户界面

15 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

类 :Labellb = Label( 窗口 ,选项设置 ) text: 标签文本内容 width: 标签宽度 fg:前景色 (文本颜色 )

例如>>> aLabel = Label(root,text="Hello World") >>> aLabel.pack() >>> Label(root,text='red color',fg='red').pack()

注意写法 : 对象创建与方法调用合二为一

常用构件常用构件 :: 标签标签

Page 16: 第 8 讲 图形用户界面

16 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

类 :Buttonbtn = Button( 窗口 ,选项设置 ) text: 按钮上的文本 command: 点击按钮时要执行的命令

需要提供一个函数或方法名 f注意不是函数调用 f()

height,width fg,bg relief: “flat/groove/raised/ridge/solid/sunken” state: “active/disabled/normal”

常用构件常用构件 :: 按钮按钮

Page 17: 第 8 讲 图形用户界面

17 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

下例中按钮对应的函数是 root 对象的方法 quit>>> b=Button(root,text="Quit",command=root.quit)>>> b.pack()>>> root.mainloop() # 点击按钮退出主循环 ,回到 >>>

下例中按钮对应的函数是自定义函数>>> def hiButton():... print 'hi there'...>>> Button(root,text='print',command=hiButton).pack()

例例 :: 按钮按钮

Page 18: 第 8 讲 图形用户界面

18 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

类 :Checkbuttoncb = Checkbutton( 窗口 ,选项设置 ) text

>>> Checkbutton(root,text="Math").pack()>>> Checkbutton(root,text="Python").pack()>>> Checkbutton(root,text="English").pack()>>> v = IntVar()>>> Checkbutton(root,text="Check",variable=v).pack()

variable: IntVar 类型的控制变量程序中可以通过 v.get() 和 v.set() 来查询或设置勾选钮的状态

常用构件常用构件 ::勾选钮勾选钮

Page 19: 第 8 讲 图形用户界面

19 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

类 :Radiobuttonrb = Radiobutton( 窗口 ,选项设置 ) value: 每个单选钮对应一个值 , 用于控制变量 variable: IntVar 类型的控制变量

一组单选钮共用一个控制变量>>> v = IntVar()>>> v.set(1)>>> Radiobutton(root,text="One",variable=v,value=1).pack()>>> Radiobutton(root,text="Two",variable=v,value=2).pack()>>> Radiobutton(root,text="Three",variable=v,value=3).pack()

常用构件常用构件 :: 单选钮单选钮

Page 20: 第 8 讲 图形用户界面

类 Entry: 单行文本编辑e = Entry( 窗口 ,选项设置 ) textvariable: StringVar 类型的控制变量 例如

>>> v = StringVar()>>> e = Entry(root,textvariable = v)>>> e.pack() >>> print v.get()hello >>> v.set('new text')

常用构件常用构件 ::文本编辑区文本编辑区

20

Page 21: 第 8 讲 图形用户界面

21 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

类 Frame: 构件容器 , 用于窗口分隔f = Frame( 窗口 ,选项设置 ) width,height,bd,relief 框架中的子构件独立地进行布局

例如>>> f = Frame(root,bd=4,relief="groove")>>> f.pack()>>> Checkbutton(f,text="Math").pack()>>> Checkbutton(f,text="Python").pack()>>> Checkbutton(f,text="English").pack()

常用构件常用构件 :: 框架框架

Page 22: 第 8 讲 图形用户界面

22 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

类 Menu ,创建菜单构件: 创建一个菜单构件实例 与某个窗口(根窗口或者顶层窗口)进行关联 为该菜单添加菜单项。

简单命令 :add_command级联式菜单 :add_cascade勾选钮 :add_checkbutton一组单选钮 :add_radiobutton

例如>>> m = Menu(root)>>> root.config(menu = m)>>> m.add_command(label="File")>>> m.add_command(label="Help")

常用构件常用构件 :: 菜单菜单

Page 23: 第 8 讲 图形用户界面

23 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

def callback(): print "hello from menu" root = Tk()m = Menu(root)root.config(menu = m)filemenu = Menu(m)m.add_cascade(label="File", menu=filemenu)filemenu.add_command(label="New", command=callback)filemenu.add_command(label="Open...", command=callback)filemenu.add_separator()filemenu.add_command(label="Exit", command=callback)helpmenu = Menu(m)m.add_cascade(label="Help", menu=helpmenu)helpmenu.add_command(label="About...", command=callback)

菜单编程例菜单编程例 ::eg8_4.pyeg8_4.py以 m 为父构件创建

菜单构件filemenu

将 filemenu设为 m的菜单项 File的子

菜单

添加分割线

Page 24: 第 8 讲 图形用户界面

类 Toplevel 顶层窗口是根窗口的子构件根窗口的子构件 ,但有一定的独立性 :可以移动 ,

改变大小 . 根窗口只有一个 ,顶层窗口可有多个 .

例如>>> root = Tk()>>> Label(root,text="hello").pack()>>> top = Toplevel()>>> Label(top,text="world").pack()>>> top.title('hello toplevel')>>> top.geometry('400x300')

常用构件常用构件 :: 顶层窗口顶层窗口

24

无需指明其父构件

Page 25: 第 8 讲 图形用户界面

25 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

布局 : 界面元素在界面中的位置安排 .布局管理器布局管理器 :: 程序员不需要了解底层显示系统的细节 , 在较高层次上考虑界面布局

构件都是先创建 , 再布局 :w = Constructor(parent,...)

w.GeometryManager(...)

Tkinter 提供三种布局管理器 :Pack,GridPack,Grid 和 Place

布局布局

Page 26: 第 8 讲 图形用户界面

26 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

Pack 以紧凑方式紧凑方式将构件在窗口中“打包” 设想窗口由弹性材料制成 ,放入构件时先把窗口空间撑大到足够

容纳该构件 , 然后将构件紧贴内部的某条边 ( 缺省是顶边 )放入 .

缺省情形下放入同一个窗口的所有构件是沿垂直方向自顶向下沿垂直方向自顶向下一个紧贴一个进行布置的可以通过 pack 方法的 side选项设置成沿水平方向打包 .

pack_forget()

将用 pack() 布局的构件从界面拿掉,变为不可见。

PackPack 布局管理器布局管理器

Page 27: 第 8 讲 图形用户界面

27 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

>>> Label(root,text="Input a number:").pack()>>> Entry(root).pack()>>> Button(root,text="OK").pack()

>>> Label(root,text="Input a number:").pack(sideside="left")>>> Entry(root).pack(side="left")>>> Button(root,text="OK").pack(side="left")

例例 ::PackPack 布局管理器布局管理器

贴左放置

Page 28: 第 8 讲 图形用户界面

28 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

Grid 将窗口或框架视为由行和列构成的二维表格二维表格 ,并将构件放入行列交叉处的单元格中 根据构件大小自动调整行列尺寸 :列宽由该列中最宽构件列中最宽构件决定 ,

行高由该行最高的构件该行最高的构件决定 .构件都有 grid() 方法

选项 row 和 column 指定行列编号从 0开始编号row 的缺省值为当前下一空行下一空行 ,column 的缺省值总为 00

选项 sticky: 指定构件在单元格内的对齐方式 ( 方位 )方位值用 "+" 组合 : 延伸构件尺寸以填满单元格

Sticky=E+W

选项 rowspan 和 columnspan:占据多个单元格

GridGrid 布局管理器布局管理器

Page 29: 第 8 讲 图形用户界面

29 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

>>> Label(root,text="ID Number:").grid() # 0,0>>> Label(root,text="Name:").grid() # 1,0>>> Entry(root).grid(row=0,column=1)>>> Entry(root).grid(row=1,column=1)

例例 ::GridGrid 布局管理器布局管理器

Page 30: 第 8 讲 图形用户界面

30 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

>>> Label(root,text="ID Number:").grid(sticky=E)>>> Label(root,text="Name:").grid(sticky=E)>>> Entry(root).grid(row=0,column=1)>>> Entry(root).grid(row=1,column=1)>>> Checkbutton(root,text="Registered User").grid(... columnspan=2,sticky=W)>>> Label(root,text="X").grid(row=0,column=2,... columnspan=2,rowspan=2,sticky=W+E+N+S)>>> Button(root,text="Zoom In").grid(row=2,column=2)>>> Button(root,text="Zoom Out").grid(row=2,column=3)

例例 ::GridGrid 布局管理器布局管理器

Page 31: 第 8 讲 图形用户界面

31 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

>>> f1 = Frame(root,width=100,height=100,bd=4,relief="groove")>>> f1.grid(row=1,column=1,rowspan=2,sticky=N+S+W+E)>>> Checkbutton(f1,text="PC").grid(row=1,sticky=W)>>> Checkbutton(f1,text="Laptop").grid(row=2,sticky=W)>>> f2 = Frame(root,width=100,height=50,bd=4,relief="groove")>>> f2.grid(row=1,column=2,columnspan=2,sticky=N)>>> b1 = Button(root,text="OK",width=6)>>> b1.grid(row=2,column=2,sticky=E+W,padx=2)>>> b2 = Button(root,text="Cancel",width=6)>>> b2.grid(row=2,column=3,sticky=E+W,padx=2)

例例 ::GridGrid 布局管理器布局管理器

Page 32: 第 8 讲 图形用户界面

32 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

事件:针对应用程序所发生的事情,并且需要应用程序对它做出响应或进行处理。

Tkinter 事件可以用特定形式的字符串来描述字符串来描述,称为事事件模式件模式,一般形式为:

"<"< 修饰符修饰符 -- 类型符类型符 -- 细节符细节符 >">"类型符 : 指定事件类型 , 如 Button 和 Key

修饰符 ( 可选 ):描述双击 , 组合键等细节符 ( 可选 ): 指定具体鼠标或键盘按键简化形式,例如 "<Double-Button-1>"

TkinterTkinter 事件驱动编程事件驱动编程

Page 33: 第 8 讲 图形用户界面

33 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

<ButtonPress-1> 或 <Button-1> 或 <1>: 单击左键 类似有 <Button-2> 和 <Button-3>

<B1-Motion>: 按下左键并移动 类似有 <B2-Motion> 和 <B3-Motion>

<Double-Button-1>:双击左键 <Enter> 和 <Leave>: 鼠标指针进入 /离开构件区域

常用鼠标事件常用鼠标事件

Page 34: 第 8 讲 图形用户界面

34 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

常用键盘事件常用键盘事件<Key-a> 或 a: 按下字母 a

可打印字符都类似 ,但空格是 <space>, 小于号是 <less>

注意 :1 和 <1> 不同 !<Return>: 按下回车键

非 可 打 印 字 符 都 类 似 , 如 :<Tab>, <Shift_L>, <Control_R>, <Up>, <Down>, <F1> 等

<Key>: 按下任意键 <Shift-Up>:同时按下 Shift 和↑键

类似的有 Alt 组合、 Ctrl 组合

鼠标事件

Page 35: 第 8 讲 图形用户界面

35 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

事件对象事件对象每个事件都创建一个事件对象 (Event 类的实例 ),并将该对象传递给事件处理函数

事件对象具有若干描述事件的属性 : x 和 y: 鼠标点击位置 ( 相对于构件左上角 ) x_root 和 y_root: 鼠标点击位置 ( 相对于屏幕左上角 ) num: 点击的鼠标键号 (1 、 2 、 3)

char: 按下的字符 (ASCII); 如果按下特殊键则为空串 keysym: 按下的字符 (ASCII); 如果按下特殊键则为该键的名

称 ( 是个字符串 )

Page 36: 第 8 讲 图形用户界面

36 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

GUI 应用程序在建立图形界面等初始化工作后进入事件循环事件循环 , 等待事件发生并触发触发绑定的事件处理程序 mainloop() 方法 : 进入事件循环

绑定 : 建立事件与事件处理程序间的对应

事件处理事件处理

Page 37: 第 8 讲 图形用户界面

37 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

语法 :

<< 构件实例构件实例 >.bind(<>.bind(< 事件描述符事件描述符 >,<>,< 事件处理程序事件处理程序>)>)

语义 : 若针对 < 构件实例 > 发生了与 < 事件描述符 >相匹配的事件 ,则调用 < 事件处理程序 > 调用事件处理程序时 , 系统传递 Event 对象作为实参 .

< 事件处理程序 > 一般是由用户自定义的函数 .

这种函数在应用程序中定义但不由应用程序调用 ,而是由系由系统调用统调用 , 一般称为回调回调 ((callbackcallback)) 函数函数

GUI 应用程序可封装为类封装为类 ,这时事件处理程序常定义为应用程序类的方法 . (详后 )

构件绑定事件构件绑定事件

Page 38: 第 8 讲 图形用户界面

38 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

eg8_6.pyfrom Tkinter import *

def callback(event): print "clicked at",event.x,event.y

root = Tk()f = Frame(root,width=100,height=100)f.bind("<Button-1>",callback)f.pack()root.mainloop()

例例 :: 框架绑定鼠标事件框架绑定鼠标事件

Page 39: 第 8 讲 图形用户界面

39 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

按键时 , 界面中哪个构件响应该键盘事件 ? 占有界面焦点焦点的构件,例 eg8_7.py

from Tkinter import *

def printInfo(event): print "pressed", event.char

root = Tk()b = Button(root,text = 'Press any key') b.bind('<Key>',printInfo) b.focus_set() b.pack() root.mainloop()

例例 :: 按钮绑定键盘事件按钮绑定键盘事件

设置焦点位置

Page 40: 第 8 讲 图形用户界面

40 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

一个构件可以响应多种事件 例,同时响应鼠标和键盘, eg8_8.py:

from Tkinter import *

def callback1(event): print "pressed", event.char

def callback2(event): f.focus_set() print "clicked at", event.x, event.y

root = Tk()f = Frame(root,width=100,height=100)f.bind("<Key>",callback1)f.bind("<Button-1>",callback2)f.pack()root.mainloop()

例例 :: 绑定多个事件绑定多个事件

Page 41: 第 8 讲 图形用户界面

41 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

GUI 编程经常将整个应用程序封装成类 在类中建立图形界面 , 定义事件处理方法 .

好处事件处理函数是类的方法,自然可以访问类中所有实例变量只要将构件存储为实例变量,就能实现处理代码与图形界面的“无缝集成” .

Tkinter 编程时,根据需要可有多种方式建立程序主窗口

独立创建根窗口 依赖外部跟窗口 ……

应用程序作为对象应用程序作为对象

Page 42: 第 8 讲 图形用户界面

42 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

class MyApp: def __init__(self): root = Tk() b = Button(root,...) ... root.mainloop()

def f(): ...

app = MyApp()

例例 :: 程序类独立创建根窗口程序类独立创建根窗口

如果一个构件具有“全局性”,即多个方法都要访问该元素,那么就需用一个实例变量来存储(引用)这个构件

Page 43: 第 8 讲 图形用户界面

43 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

class MyApp: def __init__(self,master): f = Frame(master,...) b = Button(f,...) ...

root = Tk()app = MyApp(root)root.mainloop()

例例 :: 程序类依赖外部根窗口程序类依赖外部根窗口

Page 44: 第 8 讲 图形用户界面

44 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

class MyApp: def __init__(self): self.root = Tk() self.t = Label(self.root,text="Spam") self.t.pack() Button(self.root,text="Play",command=self.changeText).pack() Button(self.root,text="Quit",command=self.root.quit).pack() self.root.mainloop() self.root.destroy() def changeText(self): if self.t["text"] == "Spam": self.t["text"] = "Egg" else: self.t["text"] = "Spam"

app = MyApp()

例例 :myapp.py :myapp.py (( eg8_11eg8_11 ))

关闭根窗口

Page 45: 第 8 讲 图形用户界面

45 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

复杂程序常可分解成核心逻辑和用户界面两部分 模型:为应用问题建模,管理应用问题的数据和行为,

对来自 UI 的数据请求或数据更新指令进行响应 视图:负责显示模型的当前数据状态 ,响应用户的交

互动作 优点:模型和视图相互独立 , 可以分开设计和测试

模型模型 -- 视图(视图(MVMV )设计方法)设计方法

model view

controller

MVCMVC

Page 46: 第 8 讲 图形用户界面

46 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

设计图形界面的汇率换算器,实现外币和人民币间换算。程序规格

汇率换算器程序用于在外币与人民币之间进行换算。

输入:外币币种,换算方向,金额

输出:等值的目标币种金额

编程案例编程案例 :: 汇率换算器汇率换算器

Page 47: 第 8 讲 图形用户界面

47 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

将应用程序模型部分封装成一个类 CCApp , 该类的实例需要记录当前的汇率信息 需要实现构造器方法 __init__ 程序启动方法 run。

将界面也封装成对象 xInterface。

编程案例编程案例 :: 汇率换算器汇率换算器

Page 48: 第 8 讲 图形用户界面

48 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

实现模型class CCApp: def __init__(self, inter): self.xRate = {'USD':6.306, 'Euro':8.2735, 'Yen':0.0775, 'Pound':10.0486} self.interface = inter

def run(self): while True: gFlag,to,fc,amount = self.interface.getInfo() if gFlag: break elif to == 'RMB': result = amount * self.xRate[fc] else: result = amount / self.xRate[fc] self.interface.showInfo(result)

编程案例编程案例 :: 汇率换算器汇率换算器

gFlag:退出标志to:换算方向fc:换算的外币amount:换算的金额

代表程序的界面 ( 尚未设计 )

Page 49: 第 8 讲 图形用户界面

49 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

设计界面 选择要换算的外币种类,每次处理一种外币,用单选钮实现; 输入和显示外币及等价人民币的金额,可用两个录入框实现; 双向换算和退出用三个命令按钮实现。

编程案例编程案例 :: 汇率换算器汇率换算器

Page 50: 第 8 讲 图形用户界面

50 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

gui.py

编程案例编程案例 :: 汇率换算器汇率换算器

from Tkinter import *

class GUInterface: def __init__(self): self.root = Tk() self.root.title("Currency Converter")

self.qFlag = False # Quit flag self.fc = StringVar() # foreign currency selected self.fc.set('USD') self.to = 'RMB' # convert to? self.amt = 0 # amount to be converted self.aRMB = StringVar() # amount of RMB self.aRMB.set('0.00') self.aFC = StringVar() # amount of foreign currency self.aFC.set('0.00')

Page 51: 第 8 讲 图形用户界面

51 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

Label(self.root,textvariable=self.fc).grid( row=0,column=0,sticky=W) Label(self.root,text='RMB').grid( row=0,column=2,sticky=W) self.e1 = Entry(self.root,textvariable=self.aFC) self.e1.grid(row=1,column=0,rowspan=2) self.e2 = Entry(self.root,textvariable=self.aRMB) self.e2.grid(row=1,column=2,rowspan=2) self.b1 = Button(self.root, text='---->',command=self.toRMB) self.b1.grid(row=1,column=1) self.b2 = Button(self.root, text='<----',command=self.toFC) self.b2.grid(row=2,column=1)

编程案例编程案例 :: 汇率换算器汇率换算器

Page 52: 第 8 讲 图形用户界面

52 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

编程案例编程案例 :: 汇率换算器汇率换算器self.f = Frame(self.root)

self.f.grid(row=3,column=0,columnspan=3) self.r1 = Radiobutton(self.f,text='USD', variable=self.fc,value='USD') self.r1.grid(row=0,column=0) self.r2 = Radiobutton(self.f,text='Euro', variable=self.fc,value='Euro') self.r2.grid(row=0,column=1) self.r3 = Radiobutton(self.f,text='Yen', variable=self.fc,value='Yen') self.r3.grid(row=0,column=2) self.r4 = Radiobutton(self.f,text='Pound', variable=self.fc,value='Pound') self.r4.grid(row=0,column=3) self.rate = Button(self.root,text='Update Rates') self.rate.grid(row=4,column=1) self.qb = Button(self.root,text='Quit',command=self.close) self.qb.grid(row=5,column=1)

Page 53: 第 8 讲 图形用户界面

53 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

def getInfo(self): self.root.mainloop() return self.qFlag,self.fc.get(),self.to,self.amt

def showInfo(self,r): rStr = "%.2f" % r if self.to == 'RMB':self.aRMB.set(rStr) else:self.aFC.set(rStr)

def toRMB(self): self.to = 'RMB' self.amt = eval(self.aFC.get()) self.root.quit() def toFC(self): self.to = self.fc.get() self.amt = eval(self.aRMB.get()) self.root.quit() def close(self): self.qFlag = True self.root.quit() self.root.destroy()

编程案例编程案例 :: 汇率换算器汇率换算器

Page 54: 第 8 讲 图形用户界面

54 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

使用from ccapp import CCApp

from gui import GUInterface

inter = GUInterface()

cc = CCApp(inter)

cc.run()

编程案例编程案例 :: 汇率换算器汇率换算器

Page 55: 第 8 讲 图形用户界面

55 of 43Room 234, No.1 Building Donghua University, Shanghai, ChinaPhone 021- 67792289

[email protected]

EndEnd

55