python核心编程(第三版) 第五章 -GUI编程

版权声明:本文为博主原创文章,欢迎转载。 https://blog.csdn.net/fww330666557/article/details/82914536

一、基本概念

python3默认的UI工具包是tkinter.
顶层窗口: 包含具体窗口内容的容器是顶层窗口;
控件:顶层窗口上可以包含一些小的窗口组件,称之为控件;
根窗口: GUI程序可以有多个顶层窗口,但只能有一个顶层窗口是根窗口。
控件可以独立存在,也可以作为容器存在。
包含其它控件的控件被称为那些控件的父控件,而被包含的控件叫做该控件的子控件;
一个GUI程序从开始到结束是通过整套事件体系来驱动的,这种方式称为事件驱动处理;
tkinter有三种布局管理器来帮助控件集进行定位:Place,Pack,Grid;
当所有控件都摆好之后,程序就可以进入无限的主循环之中,所有其它的行为都通过回调来处理。

二、pack布局

因为UI暂时不是我学习的重点,因此这里仅记录pack布局方式。
更多内容可参考:
http://effbot.org/tkinterbook/tkinter-index.htm

pack布局管理器在行和列上对控件进行组织。你可以使用的选项包括:fill, expand, and side。
何时使用pack布局:

  1. 将一个控件填满其父容器控件
  2. 将数个控件纵向排列
  3. 将数个控件横向排列

示例1:

from tkinter import *

root = Tk()

listbox = Listbox(root)
listbox.pack()

for i in range(20):
    listbox.insert(END, str(i))

mainloop()

默认显示,20个数字只显示出来10个,此时我们会去拖动窗口,让窗口尺寸变大。
在这里插入图片描述
尺寸改变之后,listbox的大小并未改变,显示效果不好:
在这里插入图片描述

改进如下:

listbox.pack(fill=BOTH, expand=1)

我们给pack方法给了两个参数,那么listbox的尺寸就会跟随父控件的尺寸而变化了:
在这里插入图片描述

示例2:

在这里插入图片描述

#!/usr/bin/env python3
#-*- coding:utf-8 -*-
' a test module '

__author__ = 'TaoGuan'


from tkinter import *

root = Tk()

w = Label(root, text="Red", bg="red", fg="white")
w.pack()
w = Label(root, text="Green", bg="green", fg="black")
w.pack()
w = Label(root, text="Blue", bg="blue", fg="white")
w.pack()

mainloop()

可以使用fill=X,让子控件与父控件等宽:
在这里插入图片描述

from tkinter import *

root = Tk()

w = Label(root, text="Red", bg="red", fg="white")
w.pack(fill=X)
w = Label(root, text="Green", bg="green", fg="black")
w.pack(fill=X)
w = Label(root, text="Blue", bg="blue", fg="white")
w.pack(fill=X)

mainloop()

示例3

在这里插入图片描述

from tkinter import *

root = Tk()

w = Label(root, text="Red", bg="red", fg="white")
w.pack(side=LEFT)
w = Label(root, text="Green", bg="green", fg="black")
w.pack(side=LEFT)
w = Label(root, text="Blue", bg="blue", fg="white")
w.pack(side=LEFT)

mainloop()

三、常用控件演示

#!/usr/bin/env python3
#-*- coding:utf-8 -*-
' Lable and Button'

__author__ = 'TaoGuan'

import tkinter as tk
import tkinter.messagebox
from PIL import Image, ImageTk

class APP():
    def __init__(self, master):
        # 加载图标
        self.icon = Image.open('test.ico')
        self.icon = ImageTk.PhotoImage(self.icon)
        # 窗口标题
        master.title('测试窗口')
        # 窗口主菜单
        self.setupMainMenus(master)
        # 创建frame
        self.frame = tk.Frame(master)
        self.frame.pack()
        # Label
        self.setupLabels(self.frame)
        # Button
        self.setupButtons(self.frame)
        # CheckButton
        self.setupCheckButtons(self.frame)
        # RadioButton
        self.setupRadioButtons(self.frame)
        # Entry
        self.setupInputBox(self.frame)
        # Message
        self.setupMessages(self.frame)
        # Canvas
        self.setupCanvases(self.frame)
        # 鼠标事件
        self.mouseEventsSetup(self.frame)
        # 键盘事件
        self.keyEventsSetup(self.frame)
        
    # 弹出提示信息
    def callback(self):
        tkinter.messagebox.showinfo('提示','人生苦短, 我用python!')
    # 构造主菜单
    def setupMainMenus(self, master):
        mainmenu = tk.Menu(master)
        master.config(menu=mainmenu)

        filemenu = tk.Menu(mainmenu)
        mainmenu.add_cascade(label="File", menu=filemenu)
        filemenu.add_command(label="New", command=self.callback)
        filemenu.add_command(label="Open...", command=self.callback)
        filemenu.add_separator()
        filemenu.add_command(label="Exit", command=self.callback)

        helpmenu = tk.Menu(mainmenu)
        mainmenu.add_cascade(label="Help", menu=helpmenu)
        helpmenu.add_command(label="About...", command=self.callback)
    def setupButtons(self, master):
        frame1 = tk.Frame(master)
        frame1.pack()
        # button除了能显示文字和图像外,还可以跟用户产生交互,执行指定的动作
        tk.Button(frame1, text='我是普通按钮,点我', command=self.callback).pack(anchor=tk.W)
        tk.Button(frame1, text="我是图文按钮,点我", image=self.icon, compound=tk.RIGHT, command=self.callback).pack(anchor=tk.W)
        tk.Button(frame1, text='我是被禁用的按钮,点我没反应', command=self.callback, state=tk.DISABLED).pack(anchor=tk.W)
        mb = tk.Menubutton(frame1, text='菜单按钮')
        mb.pack(anchor=tk.W)
        filemenu = tk.Menu(mb)
        filemenu.add_command(label='打开', command=self.callback)
        filemenu.add_command(label='保存', command=self.callback)
        filemenu.add_command(label='退出', command=root.quit) 
        mb.config(menu=filemenu)
    def setupLabels(self, master):
        frame1 = tk.Frame(master)
        frame1.pack()
        # label用来显示一些描述性的信息,比如显示文字和图像
        tk.Label(frame1,text='我是一个普通Label').pack(anchor=tk.W)
        tk.Label(frame1, text='我是一个图文Label', image=self.icon, compound=tk.RIGHT).pack(anchor=tk.W)

    def setupCheckButtons(self, master):
        frame1 = tk.Frame(master)
        frame1.pack()
        ck1 = tk.Checkbutton(frame1, text='boy')
        ck1.select()
        ck1.pack(anchor=tk.W)
        tk.Checkbutton(frame1, text='girl').pack(anchor=tk.W)
        
    def setupRadioButtons(self, master):
        frame1 = tk.Frame(master)
        frame1.pack()

        frame2 = tk.Frame(master)
        frame2.pack()

        MODES = [
            ("Monochrome", "1"),
            ("Grayscale", "L"),
            ("True color", "RGB"),
            ("Color separation", "CMYK"),
        ]
        v1 = tk.StringVar()
        v2 = tk.StringVar()
        v1.set("L") # initialize
        v2.set("1") # initialize
        for text, mode in MODES:
            b = tk.Radiobutton(frame1, text=text,
                    variable=v1, value=mode, indicatoron=1)
            b.pack(anchor=tk.W)
        for text, mode in MODES:
            b = tk.Radiobutton(frame2, text=text,
                    variable=v2, value=mode, indicatoron=0)
            b.pack(anchor=tk.W)
    def setupInputBox(self, master):
        frame1 = tk.Frame(master)
        frame1.pack()
        self.e = tk.Entry(frame1)
        self.e.pack()
        #self.e.focus_set()
        tk.Button(frame1, text='点我', command=self.showInputText).pack(anchor=tk.W)
    def showInputText(self):
        tkinter.messagebox.showinfo('提示',self.e.get())
    def setupMessages(self, master):
        frame1 = tk.Frame(master)
        frame1.pack()
        tk.Message(frame1, text="this is a message").pack(anchor=tk.W)
        tk.Message(frame1, text="this is a relatively long message", width=50).pack(anchor=tk.W)
    def setupCanvases(self, master):
        frame1 = tk.Frame(master)
        frame1.pack()
        ww = tk.Canvas(frame1, width=200, height=100)
        ww.pack()
        ww.create_line(0, 0, 200, 100)
        ww.create_line(0, 100, 200, 0, fill="red", dash=(4, 4))
        ww.create_rectangle(50, 25, 150, 75, fill="blue")
    def mouseEventsSetup(self, master):
        frame1 = tk.Frame(master)
        frame1.pack()
        self.clrIndex1 = 0
        lab = tk.Label(frame1, text='我会变色,我现在是绿色', bg = 'green')
        lab.pack(anchor=tk.W)
        lab.bind("<Enter>", self.mouseEnterCallBack)# 鼠标进入控件
        
    def keyEventsSetup(self, master):
        frame1 = tk.Frame(master)
        frame1.pack()
        self.labchar = tk.Label(frame1, text='char:', bg = 'red')
        self.labchar.pack(anchor=tk.W)
        self.labkeycode= tk.Label(frame1, text='keycode:', bg = 'yellow')
        self.labkeycode.pack(anchor=tk.W)
        self.labkeysym = tk.Label(frame1, text='keysym:', bg = 'green')
        self.labkeysym.pack(anchor=tk.W)
        self.labtype = tk.Label(frame1, text='type:', bg='pink')
        self.labtype.pack(anchor=tk.W)
        self.frame.bind('<Key>',self.keyboardCallBack)
        self.frame.focus_set()

    def mouseEnterCallBack(self, event):
        if self.clrIndex1== 0:
            event.widget['background']='red'
            event.widget['text']='我会变色,我现在是红色'
            self.clrIndex1=1
        else:
            event.widget['background']='green'
            event.widget['text']='我会变色,我现在是绿色'
            self.clrIndex1=0
    def keyboardCallBack(self, event):
        self.labchar['text'] = 'char:' + event.char
        self.labkeycode['text']= 'keycode:' + str(event.keycode) 
        self.labkeysym['text']='keysym:' + str(event.keysym) 
        self.labtype['text']='type:' + str(event.type)
# 创建root窗口   
root = tk.Tk()
# 创建app对象
app = APP(root)
# 进入主循环
root.mainloop()

猜你喜欢

转载自blog.csdn.net/fww330666557/article/details/82914536