6

【tkinter】GUI设计

 3 years ago
source link: https://www.guofei.site/2018/01/28/tkinter.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

【tkinter】GUI设计

2018年01月28日

Author: Guofei

文章归类: 7-可视化 ,文章编号: 764


版权声明:本文作者是郭飞。转载随意,但需要标明原文链接,并通知本人
原文链接:https://www.guofei.site/2018/01/28/tkinter.html

Edit

tkinter的特点

  • 简单,相比其它GUI设计包,只有基本功能
  • 内置于Python,跨平台

一般的程序架构

tk=tkinter.Tk()
tk.wm_title('中文标题')
label1=tkinter.Label(tk,text='Label')

label1['width']=20
label1['height']=4
label1['background']='red'

label1.pack()
tk.mainloop()

1. Tk()

创建一个新窗口对象

tk=tkinter.Tk()
tk.title("This is a title") #窗口的标题
tk.geometry("40x20") #窗口的默认大小,x是字母
tk.mainloop() # 时间循环

2. 控件属性

如示例程序,可以在生成控件时设定控件属性,也可以用类似dict的方法修改控件属性

通用的控件属性

  • Dimensions:尺寸
  • Colors:颜色
  • Fonts:字体
  • Anchor:锚(文本相对应位置参考点)
    • nw, n, ne, w, center, e, sw, s, se
  • Relief styles:浮雕式
  • Bitmaps:显示位图
  • Cursors:光标的外形

3. 界面布局

三种界面布局方式,pack, grid, place

3.1 pack()

默认从上往下排
有以下参数:(用这些参数做布局往往很复杂,建议不用)

  • side:指定停靠在哪个方向,可以是’left’,’top’,’right’,’bottom’
  • fill:’x’,’y’,’both’,’none’,表示填充方法:水平填充,竖直填充,双向填充,不填充
  • expand:YES,NO
  • anchor:(见于通用属性)
  • ipadx:内边距的横方向
  • ipady:内边距的竖直方向
  • padx:外边距的横方向
  • pady:外边距的竖直方向

3.2 grid()

可以把界面设置成数行数列,好处是无论如何拖动窗口,相对位置都不会变化

  • row,column 从0开始的数,行数和列数
  • rowspan, columnspan 从1开始的数,表表示跨越的行数或列数,默认是1
  • stiky: 空间的对齐方式,’n’,’e’,’w’,’s’
  • ipadx, ipady, padx, pady, x, y方向内外边距
import tkinter
tk=tkinter.Tk()
tkinter.Label(tk,text='姓名').grid(row=0,column=0,sticky='e')
tkinter.Entry(tk).grid(row=0,column=1,sticky='e')

tkinter.Label(tk,text='密码').grid(row=1,column=0,sticky='e')
tkinter.Entry(tk).grid(row=1,column=1,columnspan=1,sticky='w')

tkinter.Button(tk,text='登录').grid(row=2,column=1)
tkinter.Button(tk,text='清空').grid(row=0,column=2,rowspan=2,columnspan=1,)#,columnspan=2)

tk.mainloop()

tkinter1.jpg

3.3 place()

不是很推荐

4. 事件绑定

bind用于绑定事件,通用写法是:

窗体对象.bind(事件类型, 回调函数)

事件类型有以下几种:

  • '<Button-1>','<Button-2>','<Button-3>'表示鼠标左中右键
  • '<KeyPress-A>'表示按下A键,A可以换成其它字母
  • '<Control-V>'表示按下ctrl+V,V可以换成其它字母
  • '<F1>'表示按下F1键

回调函数有一个输入,<ButtonPress event state=Mod1 num=1 x=111 y=21>

unbind(事件类型),解除绑定
bind_all()

5. 菜单

add_command

添加菜单项

import tkinter
tk=tkinter.Tk()
menubar=tkinter.Menu(tk)
tk['menu']=menubar
for i in ['文件','编辑','视图','关于']:
    menubar.add_command(label=i)

tk.mainloop()

tkinter2.jpg

add_cascade级联

dict_mul={'文件':['新建','打开','保存','另存为'],
          '编辑':['复制','黏贴','剪切'],
          '视图':['默认视图','新式视图'],
          '关于':['版权信息','其它说明']}

import tkinter
tk=tkinter.Tk()
menubar=tkinter.Menu(tk) # 总menu归属于tk
tk['menu']=menubar
for i in dict_mul:
    temp=tkinter.Menu(menubar) # 子menu归属于menubar
    menubar.add_cascade(label=i,menu=temp)
    for j in dict_mul[i]:
        temp.add_command(label=j)
tk.mainloop()

add_separator

插入一个横杠,与正常add_command一样,只是无需参数

15个常见控件

Button()

button1=tkinter.Button(tk,text="接受此票",command=process_button1)
button_accept=tkinter.Button(tk,text="接受此票",bg="blue",fg="#777")#背景颜色,字体颜色
button_accept.pack(side=tkinter.LEFT)#这里设置位置TOP,BOTTOM,LEFT,RIGHT
#pack还有expand,side,fill选项

  • process_button1 是一个函数
  • bitmap, compound, width, height, anchor, fg, bg, relief

Canvas()

import tkinter
tk=tkinter.Tk()
canvas=tkinter.Canvas(tk,width=200,height=200)
canvas.create_text(180,20,text="文字",fill="blue",font=("time",16))

canvas.create_line((0,0),(200,200),width=8) # 起点坐标和终点坐标

canvas.create_polygon(10,10,100,10,100,110,fill="",outline="black")
#每两个数字构成一个点的坐标,然后依次画过去

#下面是插入图
myImage=tkinter.PhotoImage(file="CSLO_logo.png")
cvs.create_image(10,70,anchor=tkinter.NW,image=myImage)
cvs.pack()

#下面是做动画
mytriangle=canvas.create_polygon(10,10,10,60,50,35)
canvas.move(mytriangle,5,0)
canvas.itemconfig(mytriangle,fill='blue')
tk.mainloop()

Checkbutton:多选框

Entry():输入框

没有text这一属性

Frame:框架

Label()

label=tkinter.Label(tk,text="Welcome")
label=tkinter.Label(bitmap="error") #有bitmap时,text失效
  • bitmap可接收的属性(表示图形):
    • error
    • hourglass
    • questhead
    • question
    • warning
    • gray12
    • gray25
    • gray50
    • gray75
  • bg,fg表示背景色和字体色
  • width, height表示宽度和高度
  • compound表示图和文字的关系
    • left图像居左
    • right
    • bottom
    • center
  • background:背景色
    • ‘green’
    • ‘red’
    • ‘yellow’

Listbox:列表框

Menubutton:菜单按钮

Menu:滚动条控件

当内容超过可视化区域时使用,如列表框。

Message

Radiobutton:单选框

Scale:范围控件

显示一个数值刻度,为输出限定范围的数字区间

Scrollbar

滚动条控件,当内容超过可视化区域时使用,如列表框。

Text:显示多行文本

Toplevel:容器控件

用来提供一个单独的对话框,和Frame比较类似

Spinbox:输入控件

与Entry类似,但是可以指定输入范围值

PanedWindow

PanedWindow是一个窗口布局管理的插件,可以包含一个或者多个子控件。

LabelFrame:labelframe

一个简单的容器控件。常用于复杂的窗口布局

tkMessageBox:用于显示你应用程序的消息框。

实际案例

案例1:几张图以及用法

import tkinter
class CanvasDemo:
    def __init__(self):
        window = tkinter.Tk()
        window.title("CanvasDemo")

        self.canvas = tkinter.Canvas(window, width = 200, height = 100, bg = "White")
        self.canvas.pack()

        frame = tkinter.Frame(window)
        frame.pack()

        btRectangle = tkinter.Button(frame, text = "长方形", command = self.displayRect)
        btOval = tkinter.Button(frame, text="椭 圆", command=self.displayOval)
        btArc = tkinter.Button(frame, text = "圆 弧", command = self.displayArc)
        btPolygon = tkinter.Button(frame, text="多边形", command=self.displayPolygon)
        btLine = tkinter.Button(frame, text=" 线 ", command=self.displayLine)
        btString = tkinter.Button(frame, text="文 字", command=self.displayString)
        btClear = tkinter.Button(frame, text="清 空", command=self.clearCanvas)

        btRectangle.grid(row = 1, column = 1)
        btOval.grid(row=1, column=2)
        btArc.grid(row=1, column=3)
        btPolygon.grid(row=1, column=4)
        btLine.grid(row=1, column=5)
        btString.grid(row=1, column=6)
        btClear.grid(row=1, column=7)

        window.mainloop()

    def displayRect(self):
        self.canvas.create_rectangle(10, 10, 190, 90, tags = "rect")
    def displayOval(self):
        self.canvas.create_oval(10, 10, 190, 90, tags = "oval", fill = "red")
    def displayArc(self):
        self.canvas.create_arc(10, 10, 190, 90, start = 0, extent = 90, width = 8, fill = "red", tags = "arc")
    def displayPolygon(self):
        self.canvas.create_polygon(10, 10, 190, 90, 30, 50, tags = "polygon")
    def displayLine(self):
        self.canvas.create_line(10, 10, 190, 90, fill = 'red', tags = "line")
        self.canvas.create_line(10, 90, 190, 10, width = 9, arrow = "last", activefill = "blue", tags = "line")
    def displayString(self):
        self.canvas.create_text(60, 40, text = "Hi,i am a string", font = "Tine 10 bold underline", tags = "string")
    def clearCanvas(self):
        self.canvas.delete("rect", "oval", "arc", "polygon", "line", "string")

CanvasDemo()

案例2:Menubar

import tkinter
class MenuDemo:
    def __init__(self):
        window = tkinter.Tk()
        window.title("Menu demo")

        menubar = tkinter.Menu(window,bg="red")
        window.config(menu = menubar)

        #创建下拉菜单,并添加到菜单条
        operationMenu = tkinter.Menu(menubar, tearoff = 0)
        menubar.add_cascade(label = "操作", menu = operationMenu)
        operationMenu.add_command(label = "加", command = self.add)
        operationMenu.add_command(label="减", command=self.subtract)
        operationMenu.add_separator()
        operationMenu.add_command(label = "乘", command = self.multiply)
        operationMenu.add_command(label="除", command=self.divide)

        exitMenu = tkinter.Menu(menubar, tearoff = 0)
        menubar.add_cascade(label = "退出", menu = exitMenu)
        exitMenu.add_command(label = "退出", command = window.quit)

        tkinter.mainloop()

    def add(self):
        print("相加")
    def subtract(self):
        print("相减")
    def multiply(self):
        print("相乘")
    def divide(self):
        print("相除")

MenuDemo()

案例3:鼠标事件

import tkinter
class MenuDemo:

    def __init__(self):
        root = tkinter.Tk()

        # create a popup menu
        self.menu = tkinter.Menu(root, tearoff=0)
        self.menu.add_command(label="Undo", command=self.hello)
        self.menu.add_command(label="Redo", command=self.hello)

        # create a canvas
        self.frame = tkinter.Frame(root, width=512, height=512)
        self.frame.pack()

        # attach popup to canvas
        self.frame.bind("<Button-1>", self.popup)
        root.mainloop()

    def popup(self, event):
        self.menu.post(event.x_root, event.y_root)

    def hello(self):
        print("hello!")
MenuDemo()

详解:

widget.bind_all(event, handler)
  • 其中event是一个字符串,表示所触发的事件
  • handler是一个函数,触发事件后调用这个函数

  • event的值(字符串)与对应的描述
    • 当拖拽小部件的时候
    • Button-1、Button-2、Button-3表示左键、中间键、右键点击
    • 当释放鼠标的时候
    • 当双击鼠标的时候
    • 当鼠标光圈进入小部件的时候
    • 当敲击一个键时候
    • 当鼠标光圈离开小部件的时候
    • 当敲击“Enter”键时候,可以将键盘任意一个键和一个事件绑定
    • <Shift+A> 当敲击Shif+A的时候,可以和Alt、Control等组和
    • 点击鼠标3次的时候
  • handler函数的参数对应的属性
    • char 从键盘输入的字符
    • keycode 从键盘输入的键代码
    • keysym 从键盘输入的键符号,”Up”,”Down”,”Left”,”Right”
    • num 鼠标键的数字(1、2、3)
    • widget 出发这个事件的小部件的对象
    • x和y 当前鼠标在小部件的坐标(像素)
    • x_root和y_root 当前鼠标相对于屏幕左上角的坐标(像素)

move

cvs.move(i,dx,dy)
  • canvas上的第i个对象移动dx, dy

tkinter

from tkinter import *

import tkinter.simpledialog as dl
import tkinter.messagebox as mb

#tkinter GUI Input Output Example
#设置GUI
root = Tk()
w = Label(root, text = "Label Title")
w.pack()

#欢迎消息
mb.showinfo("Welcome", "Welcome Message")
guess = dl.askinteger("Number", "Enter a number")

output = 'This is output message'
mb.showinfo("Output: ", output)

参考资料

辛星tkinter教程第二版


您的支持将鼓励我继续创作!

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK