python tkinter

基本使用

基于tkinter创建 GUI基本四步:窗口->组件->布局->事件

1.创建窗口对象

from tkinter import *

root = Tk()  # 创建窗口

root.mainloop()  # 进入事件循环

2.创建组件

按钮文本等组件

btn = Button(root)  # 创建Button组件,使组件在root窗口展示
btn['text'] = '我是按钮'  # 组件属性参数

3.布局管理

管理组件的大小位置样式

btn.pack()  # 布局管理器,组件的大小位置样式

4.事件

通过与组件绑定,获取组件所触发的事件

def btn_event(obj):  # obj 即事件对象
    print('控制台输出:'+'触发了事件')  # 输出到控制台
btn.bind('<Button-1>', btn_event)  # 事件和组件进行绑定

案例:

from tkinter import *
from tkinter import messagebox

root = Tk()  # 创建窗口

btn = Button(root)  # 创建Button组件,使组件在root窗口展示
btn['text'] = '我是按钮'
btn.pack()  # 布局管理器,配置组件的样式

def btn_event(obj):  # obj 即事件对象
    messagebox.showinfo("Message","触发了事件")  # 弹出新的窗口,并展示内容
    print('控制台输出:'+'触发了事件')  # 输出到控制台

btn.bind('<Button-1>', btn_event)  # 事件绑定,事件和组件进行绑定  <Button-1> :鼠标左键点击一次  <Button-2>:鼠标右键点击一次

if __name__ == '__main__':
    root.mainloop()  # 进入事件循环

主窗口

title('窗口标题')

geometry('wxh ± x, ±y') 

  • w:宽度
  • h:高度
  • +x:距屏幕左边的距离,-x:距屏幕右边的距离
  • +y:距屏幕上边的距离,-y:距;屏幕下边的距离
root.geometry('500x300+100+200')  # 宽度500,高度300,距左边100,距上边200

组件

Toplevel顶层容器类,可为其他组件提供单独的容器,类似窗口
Button按钮按钮点击组件
Ganvas画布提供绘图功能
Radiobutton单选框单选框
CheckButton复选框可勾选的复选框
Entry单行输入框可输入内容

simpledialog其子方法

简单输入框
filedialog其子方法文件对话框用于打开系统文件
Frame容器用于装载其他组件
LabelFrame容器类似Frame,但可以添加标题
label标签显示不可编辑的文本或图标
Listbox列表框可列出多个选项
Menu菜单菜单组件
MenuButton菜单按钮包含菜单的按钮,包括下拉层叠式等
OptionMenuu菜单按钮MenuButton的子类,可通过按钮打开一个菜单
Message消息框可以显示多行文档

messagebox

通用消息框用于和用户简单的消息交互
Text文本框可显示多行文本、图片、连接、HTML页面、CSS样式,甚至可添加组件等
Scale滑块可移动滑块

askcolor

颜色

Frame容器

GUI编程就是编写一个个组件,界面由组件组成,组件内又可以创建组件,这种组件即为容器

import tkinter as tk
from tkinter import Frame

root = tk.Tk()
root.title('包含容器的GUI')
root.geometry('500x300+200+200')
frame = Frame(master=root)  # 在root中创建容器
frame.pack()

root.mainloop()

经典的面向对象的GUI

import tkinter as tk
from tkinter import *
from tkinter import messagebox

root = tk.Tk()
root.title('经典的面向对象的GUI')
root.geometry('500x300+200+200')

class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        '''创建各种组件'''
        self.btn01 = Button(self, text='容器的按钮01', command=self.btn01_event)  # 创建button组件,在Frame中显示,这里的self是Frame
        self.btn01.pack()

        self.btn02 = Button(self, text='退出', command=root.destroy)
        self.btn02.pack()

    def btn01_event(self):
        messagebox.showinfo('Message', '触发了事件')
        print('控制台输出:' + '触发了事件')  # 输出到控制台


def main():
    app = Application(root)
    root.mainloop()

if __name__ == '__main__':
    main()

 

 Label

  • font:字体和大小,1个中文宽度两个字符,高度一个字符
  • image:图片,目前支持gif
  • fg:前景色,bg:背景色
  • justigy:对齐方式,left、center、right
  • width:宽度,heigth:高度
import tkinter as tk
from tkinter import *
from tkinter import messagebox

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        '''创建各种组件'''
        # 文件标签
        self.text_label = Label(self, text='label组件',
                           width=10, height=2, bg='black', fg='white', font=('黑体', 15), justify='left', borderwidth=1)
        self.text_label.pack()
        self.text_label2 = Label(self, text='label组件\nlabel组件内容不能修改\n哈哈',
                           bg='black', fg='white', font=('黑体', 15), justify='left', borderwidth=1)
        self.text_label2.pack()
        # 图片标签
        global PHOTO
        PHOTO = PhotoImage(file='img.gif')  # 注意:图片最好是全局变量
        self.photo_label = Label(root, image=PHOTO)
        self.photo_label.pack()


def main():
    app = Application(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Button

import tkinter as tk
from tkinter import *
from tkinter import messagebox

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')

PHOTO = PhotoImage(file='img.gif')  # 注意:图片最好是全局变量


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        '''创建各种组件'''
        self.login_btn = Button(self, text='登录', command=self.login_event)  # 创建button组件,在Frame中显示,这里的self是Frame
        self.login_btn.pack()

        self.image_btn = Button(self, image=PHOTO, command=self.image_event)
        self.image_btn.pack()
        self.image_btn['state'] = 'disable'  # 按钮禁止点击

    def image_event(self):
        messagebox.showinfo('Message', '点击了图片')

    def login_event(self):
        messagebox.showinfo('Message', '登录成功')
        # print('控制台输出:' + '触发了事件')  # 输出到控制台


def main():
    app = Application(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Entry

import tkinter as tk
from tkinter import *
from tkinter import messagebox

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        '''创建各种组件'''
        self.user_label = Label(self, text='用户')
        self.user_label.pack()

        user_value = StringVar()  # 定义变量,要用来接收Entry输入的值
        user_value.set('admin')  # StringVar 的默认值
        self.user_entry = Entry(self, textvariable=user_value)  # StringVar变量绑定到Entry组件
        self.user_entry.pack()
        print(user_value.get())
        print(self.user_entry.get())

        self.pwd_label = Label(self, text='密码')
        self.pwd_label.pack()
        pwd_value = StringVar()
        self.pwd_entry = Entry(self, textvariable=pwd_value, show="*")  # 用户输入的内容展示成 *
        self.pwd_entry.pack()

        self.user_btn = Button(self, text='提交', command=self.login)
        self.user_btn.pack()

    def login(self):
        print('用户名: ' + self.user_entry.get())  # 获取输入框的值
        print('用户密码: ' + self.pwd_entry.get())  # 获取输入框的值
        messagebox.showinfo('Message', '登录成功')


def main():
    app = Application(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Text 

  • insert 插入内容到指定位置
  • get 获取指定位置的内容
  • image_create 插入图片到指定位置
  • delete 删除指定位置的内容
  • tag_add:添加标签 tag_config:标签样式 tag_bind:标签事件
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        '''创建各种组件'''

        self.text = Text(self, width=40, height=20, bg='gray')  # width=40 宽度40,可显示20列汉字 height=20 高度20,可显示20行汉字
        self.text.pack()

        # 插入数据
        self.text.insert(1.0, '123456\n')  # inster 第一个参数为插入数据的坐标 x.y  1.0表示第一行第0列

        Button(self, text='重复插入', command=self.insert_text).pack(side='left')  # pack(side='left') 表示水平排列
        Button(self, text='返回文本', command=self.return_text).pack(side='left')
        Button(self, text='添加图片', command=self.add_image).pack(side='left')
        Button(self, text='添加组件', command=self.add_widget).pack(side='left')
        Button(self, text='通过tag精准控制文本', command=self.test_tag).pack(side='left')

    def insert_text(self):
        self.text.insert(INSERT, 'AAA')  # INSERT 在光标所在位置插入内容
        self.text.insert(END, 'BBB')  # END 在文本末尾插入内容

    def return_text(self):
        print(self.text.get(1.0, 2.5))  # 获取指定范围内的文本, get(1.0, 2.5) 表示获取第1行第0列至地2行第5列的内容
        print(self.text.get(1.0, END))  # 获取全部内容

    def add_image(self):
        self.photo = PhotoImage(file='img.gif')
        self.text.image_create(END, image=self.photo)

    def add_widget(self):
        '''
        在文本框中添加按钮组件
        '''
        btn = Button(self.text, text='按钮')  # 添加的组件是在text组件中,所以一个参数是 self.text
        self.text.window_create(INSERT, window=btn)  # 将组件添加到 text组件中

    def test_tag(self):
        self.text.delete(1.0, END)
        self.text.insert(1.0, '天净沙·秋思\n马致远\n枯藤老树昏鸦,\n小桥流水人家,\n古道西风瘦马。\n夕阳西下,断肠人在天涯\n')
        # 添加 tag
        self.text.tag_add('古诗名', 1.0, 1.6)  # 第一个参数标签名,第二个参数标签范围
        # 为标签添加样式
        self.text.tag_config('古诗名', background='yellow', foreground='red', font=5)

        self.text.insert(END, '百度')
        # 为标签绑定事件
        self.text.tag_add('baidu', 7.0, 7.2)
        self.text.tag_config('baidu', underline=True)
        self.text.tag_bind('baidu', '<Button-1>', self.go_baidu)

    def go_baidu(self, event):
        webbrowser.open('http://www.baidu.com')

def main():
    app = Application(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Radiobutton

import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        '''创建各种组件'''
        # 创建变量
        self.gender = StringVar()
        self.gender.set('F')  # 设置默认值
        # 变量与单选框绑定
        self.rbtn1 = Radiobutton(self, text='男性', value='M', variable=self.gender).pack(side='left')  # variable 将用户选择的值 value赋值给self.gender
        self.rbtn2 = Radiobutton(self, text='女性', value='F', variable=self.gender).pack(side='left')

        Button(self, text='确定', command=self.confirm).pack(side='left')

    def confirm(self):
        messagebox.showinfo('Message', '选择的性别为:'+self.gender.get())


def main():
    app = Application(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Checkbutton

import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        '''创建各种组件'''
        # 创建变量
        self.code_hobby = IntVar()
        self.video_hobby = IntVar()
        print(self.code_hobby.get())  # 默认值为0

        # Checkbutton onvalue选中时的值,offvalue未选中时的值, variable将值赋值给变量
        self.cbtn1 = Checkbutton(self, text='代码', onvalue=1, offvalue=0, variable=self.code_hobby).pack(side='left')
        self.cbtn2 = Checkbutton(self, text='电影', onvalue=1, offvalue=0, variable=self.video_hobby).pack(side='left')

        Button(self, text='确定', command=self.confirm).pack(side='left')

    def confirm(self):
        hobby = []
        if self.code_hobby.get() == 1:
            hobby.append('代码')
        if self.video_hobby.get() == 1:
            hobby.append('电影')
        messagebox.showinfo('Message', '选择的爱好:' + ','.join(hobby))


def main():
    app = Application(root)
    root.mainloop()

if __name__ == '__main__':
    main()

OptionMenu 

import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        '''创建各种组件'''
        self.value = StringVar()
        self.value.set('python')
        OptionMenu(self, self.value,  'python', 'go', 'java').grid(row=1, column=0)
        Button(self, text='确定', command=self.language).grid(row=1, column=1)

    def language(self):
        print(self.value.get())


def main():
    app = Application(root)
    root.mainloop()

if __name__ == '__main__':
    main()

Menu

import tkinter as tk
import webbrowser
from tkinter import *

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        """创建各种组件"""
        # 创建菜单栏
        main_menu = Menu(self.master)
        # 创建子菜单栏
        file_menu = Menu(main_menu, tearoff=0)
        edit_menu = Menu(main_menu, tearoff=0)
        help_menu = Menu(main_menu, tearoff=0)

        # 将子菜单栏加入主菜单栏
        main_menu.add_cascade(label='文件', menu=file_menu)
        main_menu.add_cascade(label='编辑', menu=edit_menu)
        main_menu.add_cascade(label='帮助', menu=help_menu)

        # 添加菜单选项并绑定方法
        file_menu.add_command(label='新建', accelerator='Ctrl+N', command=self.create_file)
        file_menu.add_command(label='打开', accelerator='Ctrl+O', command=self.open_file)
        file_menu.add_command(label='保存', accelerator='Ctrl+S', command=self.save_file)
        file_menu.add_separator()  # 添加分割线
        file_menu.add_command(label='退出', command=root.quit)

        # 将主菜单添加到窗口
        self.master['menu'] = main_menu

    def create_file(self):
        pass

    def open_file(self):
        pass

    def save_file(self):
        pass

def main():
    app = Application(master=root)
    app.mainloop()

if __name__ == '__main__':
    main()

Scale

import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        """创建各种组件"""
        self.text_label = Label(self, text='好好学习', font=('宋体', 10))
        self.text_label.pack()
        Scale(
            self,
            from_=10, to=50, tickinterval=5,  # 从10开始到50,按每份大小为5划分
            length=200,
            orient=HORIZONTAL,  # HORIZONTAL:水平, 默认垂直
            command=self.test
        ).pack()

    def test(self, value):
        # value 是滑块的值
        print('滑块的值: ' + value)
        font = ('宋体', value)
        self.text_label.config(font=font)


def main():
    app = Application(root)
    root.mainloop()


if __name__ == '__main__':
    main()

askcolor

import tkinter as tk
import webbrowser
from tkinter import *
from tkinter.colorchooser import askcolor

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        """创建各种组件"""
        Button(self, text='选择背景色', command=self.bgcolor).pack()

    def bgcolor(self):
        c = askcolor(title='选择背景色', color='red')
        print(c[1])
        root.config(bg=c[1])


def main():
    app = Application(root)
    root.mainloop()


if __name__ == '__main__':
    main()

filedialog文本对话框

方法包括:

  • askopenfilenames:选择多个文件。
  • askopenfilename: 选中一个文件
  • askdirectory:选择一个目录。
  • asksaveasfilename:选择一个文件保存位置。
  • askopenfile:打开一个文件并返回一个文件对象。
  • asksaveasfile:选择一个文件保存位置并返回一个文件对象

askopenfilename

参数:

  • title:对话框的标题。
  • initialdir:初始目录。
  • filetypes:指定过滤的文件类型。
  • defaultextension:默认扩展名。

返回值:返回所选择文件的绝对路径,若选择的文件不存在则为空

import tkinter as tk
import webbrowser
from tkinter import *
from tkinter.filedialog import *

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        """创建各种组件"""
        self.show_file_path = Label(self)
        self.show_file_path.pack()
        Button(self, text='上传文件', command=self.file_path).pack()

    def file_path(self):
        file = askopenfilename(title='上传文件', initialdir='/', filetypes=[('文本文件', '.txt')])
        self.show_file_path['text'] = file


def main():
    app = Application(root)
    root.mainloop()


if __name__ == '__main__':
    main()

askopenfile

返回值:返回文件对象 

import tkinter as tk
import webbrowser
from tkinter import *
from tkinter.filedialog import *

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        """创建各种组件"""
        self.show_file_content = Label(self)
        self.show_file_content.pack()
        Button(self, text='上传文件', command=self.file_content).pack()

    def file_content(self):
        file = askopenfile(title='上传文件', initialdir='/', filetypes=[('文本文件', '.txt')])
        self.show_file_content['text'] = file.read()


def main():
    app = Application(root)
    root.mainloop()


if __name__ == '__main__':
    main()

 

simpledialog简单输入框

要包含了以下几种对话框方法:

  1. askstring(title, prompt, **options) 用户输入的字符串,如果用户点击了取消或关闭对话框,则返回 None
  2. askinteger(title, prompt, **options) 用户输入的整数,如果用户点击了取消或关闭对话框,则返回 None
  3. askfloat(title, prompt, **options) 用户输入的浮点数,如果用户点击了取消或关闭对话框,则返回 None

参数:

  • title:对话框的标题。
  • prompt:显示在对话框中的提示信息。
  • **options:其他选项,如 initialvalueminvaluemaxvalue 等。
import tkinter as tk
import webbrowser
from tkinter import *
from tkinter.simpledialog import *

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        """创建各种组件"""
        self.show_name = Label(self)
        self.show_name.grid(row=1, column=0)
        Button(self, text='输入姓名', command=self.name).grid(row=1, column=1)
        self.show_age = Label(self)
        self.show_age.grid(row=2, column=0)
        Button(self, text='输入年龄', command=self.age).grid(row=2, column=1)

    def name(self):
        v = askstring(title='输入姓名', prompt='请输入姓名')
        self.show_name['text'] = v

    def age(self):
        v = askinteger(title='输入年龄', prompt='请输入年龄', 
                       initialvalue=18,  # 默认值
                       minvalue=1, maxvalue=150  # 大小范围
                       )
        self.show_age['text'] = v


def main():
    app = Application(root)
    root.mainloop()


if __name__ == '__main__':
    main()

messagebox

包含的方法

  1. showinfo(title, message, **options)
    用于显示信息消息。
  2. showwarning(title, message, **options)
    用于显示警告消息。
  3. showerror(title, message, **options)

    用于显示错误消息。

  4. askquestion(title, message, **options)

    用于询问用户一个问题,并提供“是”和“否”两个选项。

  5. askokcancel(title, message, **options)

    用于询问用户一个问题,并提供“确定”和“取消”两个选项。

  6. askyesno(title, message, **options)

    用于询问用户一个问题,并提供“是”和“否”两个选项。

  7. askretrycancel(title, message, **options)

    用于询问用户是否重试,提供“重试”和“取消”两个选项。

  8. askyesnocancel(title, message, **options)

    用于询问用户一个问题,并提供“是”、“否”和“取消”三个选项。

参数:

  • title:对话框的标题。
  • message:显示的信息内容。
  • **options:其他选项,如图标、按钮文本等。

案例

import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        """创建各种组件"""
        Button(self, text='showinfo', command=self.showinfo).pack()
        Button(self, text='showwarning', command=self.showwarning).pack()
        Button(self, text='showerror', command=self.showerror).pack()
        Button(self, text='askquestion', command=self.askquestion).pack()
        Button(self, text='askokcancel', command=self.askokcancel).pack()
        Button(self, text='askyesno', command=self.askyesno).pack()
        Button(self, text='askretrycancel', command=self.askyesno).pack()
        Button(self, text='askyesnocancel', command=self.askyesno).pack()

    def showinfo(self):
        messagebox.showinfo('消息提示', '这是一条提示消息')

    def showwarning(self):
        messagebox.showwarning("警告提示", "这是一个警告提示框。")

    def showerror(self):
        messagebox.showerror("错误提示", "这是一个错误提示框。")

    def askquestion(self):
        # # 询问问题(返回 'yes' 或 'no')
        response = messagebox.askquestion("询问提示", "您确定要继续吗?")
        if response == 'yes':
            print("用户选择了 '是'。")
        else:
            print("用户选择了 '否'。")

    def askokcancel(self):
        # 询问问题(返回 True 或 False)
        response = messagebox.askokcancel("询问提示", "您确定要继续吗?")
        if response:
            print("用户选择了 '确定'。")
        else:
            print("用户选择了 '取消'。")

    def askyesno(self):
        # 询问问题(返回 True 或 False)
        response = messagebox.askyesno("询问提示", "您确定要继续吗?")
        if response:
            print("用户选择了 '是'。")
        else:
            print("用户选择了 '否'。")

    def askretrycancel(self):
        # 询问是否重试(返回 True 或 False)
        response = messagebox.askretrycancel("询问提示", "操作失败,您想重试吗?")
        if response:
            print("用户选择了 '重试'。")
        else:
            print("用户选择了 '取消'。")

    def askyesnocancel(self):
        # 询问问题(返回 True、False 或 None)
        response = messagebox.askyesnocancel("询问提示", "您确定要继续吗?")
        if response is True:
            print("用户选择了 '是'。")
        elif response is False:
            print("用户选择了 '否'。")
        else:
            print("用户选择了 '取消'。")


def main():
    app = Application(root)
    root.mainloop()


if __name__ == '__main__':
    main()

布局管理器

`tkinter` 提供了三种常用的布局管理器:`pack`、`grid` 和 `place`。每种布局管理器都有其独特的用途和特性,适用于不同的布局需求。

 pack

`pack` 是一种基于容器的布局管理器,它将组件放置在父容器中的左侧、右侧、顶部或底部。使用 `pack` 时,组件可以扩展以填充可用空间,或者收缩以适应空间。这种布局方式非常适合那些不需要精确位置控制的简单界面。

  • 组件可以扩展或收缩以适应容器大小的变化。
  • 组件可以水平或垂直排列。
  • 支持填充(fill)和扩展(expand)选项,使得组件可以占据更多的空间。
  • 不适合需要精确坐标定位的情况。

常用参数:

  • `side`:指定组件放置的位置,可以是 `TOP`、`BOTTOM`、`LEFT` 或 `RIGHT`。
  • `expand`:布尔值,指定组件是否应该扩展以占据所有可用空间。
  • `fill`:指定组件应该填充的方向,可以是 `X`、`Y` 或 `BOTH`。

grid

`grid` 布局管理器提供了一个表格形式的布局方式,可以将组件放置在一个二维网格中的单元格内。这种方式非常适合需要精确行和列定位的应用场景。

  • 组件放置在一个由行和列组成的网格中。
  • 每个组件占据一个或多个单元格。
  • 支持跨越多个行或列的组件。
  • 更适合复杂界面设计,尤其是表格式的布局。

常用参数:

  • `row` 和 `column`:指定组件所在的行和列。
  • `sticky`:指定组件如何对其所在单元格进行对齐,可以是 `N`、`S`、`E`、`W`、`NE`、`NW`、`SE`、`SW`、`NS`、`EW`、`NSW`、`NSE`、`NEW`、`NSEW`。
  • `columnspan` 和 `rowspan`:指定组件跨越的行数和列数。
  • `padx` 和 `pady`:指定组件周围的内部填充。
  • `ipadx` 和 `ipady`:指定组件内部的填充。

案例

import tkinter as tk
import webbrowser
from tkinter import *
from tkinter import messagebox

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


class Application(Frame):
    def __init__(self, master):
        super().__init__(master)

        self.master = master
        self.pack()
        self.create_widget()

    def create_widget(self):
        '''创建各种组件'''
        self.name = StringVar()
        self.name.set('admin')
        Label(self, text='账号').grid(row=1, column=0)
        Entry(self, textvariable=self.name).grid(row=1, column=1)

        self.pwd = StringVar()
        Label(self, text='密码').grid(row=2, column=0)
        Entry(self, textvariable=self.pwd).grid(row=2, column=1)

        Button(self, text='登录', command=self.login).grid(row=3, column=0)
        Button(self, text='退出', command=root.destroy).grid(row=3, column=1, sticky=E)

    def login(self):
        if self.name.get() == 'admin' and self.pwd.get() == '123456':
            messagebox.showinfo('Message', '登录成功')
        else:
            messagebox.showinfo('Message', '用户名或密码错误')


def main():
    app = Application(root)
    rows, columns = root.grid_size()
    print(f"Rows: {rows}, Columns: {columns}")
    root.mainloop()

if __name__ == '__main__':
    main()

place

`place` 布局管理器允许开发者以绝对坐标的形式来定位组件。这种方式最灵活但也最难维护,因为每个组件的位置都需要明确指定。

  • 组件位置通过坐标 `(x, y)` 明确指定。
  • 支持组件大小的精确控制。
  • 适合需要高度定制化布局的设计。
  • 由于绝对定位,可能导致布局在不同屏幕尺寸或分辨率下的表现不一致。

常用参数:

  • `x` 和 `y`:指定组件左上角的坐标。
  • `width` 和 `height`:指定组件的宽度和高度。
  • `relx`、`rely` :相对父组件坐标进行定位(值范围:0-1)
  • `relwidth`、`relheight`:相对父组件进行尺寸大小设置(值范围:0-1)。

案例

import tkinter as tk
from tkinter import *

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')

f1 = Frame(root, width=300, height=200, bg='green')
f1.place(x=30, y=30)  # f1 组件的左上角相对于其父组件(root)的距离 横向30,纵向30

Button(root, text='按钮1').place(
    relx=0.2,  # 相对父组件坐标  500 * 0.2
    x=50,  # relx 后面的 x属性 表示再向右移动
    y=100,
    relwidth=0.2,  # 相对父组件宽度 500 * 0.2
    relheight=0.5  # 相对父组件高度 300 * 0.5
)

Button(f1, text='按钮2').place(relx=0.1, rely=0.2)

root.mainloop()

选择合适的布局管理器

- 如果你的应用程序需要简单的布局,而且不需要精确的坐标定位,那么 `pack` 是一个很好的选择。
- 如果你需要一个表格形式的布局,其中每个组件的位置都可以精确控制,那么 `grid` 更适合你。
- 如果你需要绝对控制每个组件的位置和大小,那么 `place` 可以提供最大的灵活性,但也会带来更复杂的维护工作。

事件

组件绑定事件方法:

  • widget.bind(event,handler)  当需要获取event对象时
  • widget(commadn=handler)  当不需要获取event对象时
  • widget.bind_class('Button',<Button-1>, func)  将所有Button绑定事件

当事件发生,handler函数会被出发,并将事件对象event传入

import tkinter as tk
from tkinter import *

root = tk.Tk()
root.title('我是窗口')
root.geometry('500x300+200+200')


def test1():
    print('test1')


def test2(a, b):
    print(a + b)


def test3(event):
    print('test3')

# 适用事件函数不需要参数时
Button(root, text='按钮1', command=test1).pack(side='left')
# 适用事件函数需要参数时,利用lambda
Button(root, text='按钮2', command=lambda: test2(2, 5)).pack(side='left')
# 为所有Button按钮绑定鼠标右键事件
Button(root, text='按钮3').bind_class('Button', '<Button-2>', test3)

root.mainloop()

鼠标和键盘事件

event常用属性

ttk模块控件

特点

  1. 可定制性ttk 控件支持主题化,可以更容易地改变控件的外观。
  2. 跨平台一致性ttk 控件在不同操作系统上的外观更加一致。
  3. 更多的组件ttk 提供了一些 tkinter 没有的组件,例如树形控件(Treeview)、进度条(Progressbar)等。

控件

  1. ttk.Button:按钮控件。
  2. ttk.Checkbutton:复选框控件。
  3. ttk.Combobox:下拉组合框控件。
  4. ttk.Entry:输入框控件。
  5. ttk.Frame:容器控件。
  6. ttk.Label:标签控件。
  7. ttk.LabelFrame:带标签的容器控件。
  8. ttk.Menubutton:菜单按钮控件。
  9. ttk.PanedWindow:窗格控件,用于创建分割窗口。
  10. ttk.Progressbar:进度条控件。
  11. ttk.Radiobutton:单选按钮控件。
  12. ttk.Scale:滑动条控件。
  13. ttk.Separator:分隔线控件。
  14. ttk.Sizegrip:大小调整控件。
  15. ttk.Treeview:树形表格控件。

案例

import tkinter as tk
from tkinter import ttk

root = tk.Tk()
root.title('ttk 示例')
root.geometry('500x300+200+200')

# 创建一个 Frame 容器
frame = ttk.Frame(root, padding=10)
frame.pack(fill=tk.BOTH, expand=True)

# 创建一个 Label 标签
label = ttk.Label(frame, text="欢迎使用 ttk 控件!")
label.pack()

# 创建一个 Button 按钮
button = ttk.Button(frame, text="点击我")
button.pack()

# 创建一个 Entry 输入框
entry = ttk.Entry(frame)
entry.pack()

# 创建一个 Checkbutton 复选框
check_var = tk.BooleanVar()
checkbutton = ttk.Checkbutton(frame, text="同意协议", variable=check_var)
checkbutton.pack()

# 创建一个 Radiobutton 单选按钮
radio_var = tk.IntVar()
radiobutton1 = ttk.Radiobutton(frame, text="选项1", variable=radio_var, value=1)
radiobutton2 = ttk.Radiobutton(frame, text="选项2", variable=radio_var, value=2)
radiobutton1.pack()
radiobutton2.pack()

# 创建一个 Combobox 下拉组合框
combo = ttk.Combobox(frame, values=["选项A", "选项B", "选项C"])
combo.pack()

# 创建一个 Progressbar 进度条
progressbar = ttk.Progressbar(frame, length=200, mode='determinate')
progressbar.pack()

# 创建一个 Treeview 树形表格
tree = ttk.Treeview(frame, columns=("姓名", "年龄"), show='headings')
tree.heading("姓名", text="姓名")
tree.heading("年龄", text="年龄")
tree.insert("", tk.END, values=("张三", "25"))
tree.insert("", tk.END, values=("李四", "30"))
tree.pack()

root.mainloop()

《tkinter实用教程21》treeview 节点插入、单选、多选、事件、树、表格_tkinter treeview-CSDN博客

tkinter滚动条Scrollbar_tkinter 滚动条-CSDN博客 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值