编程入门10:Python图形界面

上一篇:编程入门09:Python字典类型

你已经熟悉了只在窗口中显示一块画布的“海龟绘图”,现在让我们尝试编写更通用的图形界面程序——使用Python标准库中的图形界面工具包tkinter,之前介绍的IDLE和turtle实际上都是基于tkinter实现的。tkinter的特点是简单轻便、适合入门之用,今后你也可以学习其他更“高级”的第三方包来开发图形界面——例如Spyder所使用的PyQt https://pypi.python.org/pypi/PyQt5

图形界面的各种构成元素统称“可视化部件”(Widget),每一种部件都对应某一种类型,首先你需要生成特定类型的部件对象,然后调用对象的方法即可任意控制图形界面的外观和行为了。现在让我们来制作一个最简单的图形界面程序——只包含一个最基本的部件——“窗口”,对应类型名为Tk。

import tkinter as tk

window = tk.Tk()  # 生成窗口对象
window.geometry("500x300")  # 设置窗口大小
window.title("简单图形界面程序")  # 设置窗口标题

# 这里可以生成其他部件并放入窗口

tk.mainloop()  # 开始主循环

以上程序中生成窗口对象的“Tk()”是一种特别的函数,函数名就是类型名,称为类型的“构造函数”、“构造方法”或“构造器”(Constructor),这几个术语指的都是同一样东西。任何类型的对象都可以用相应构造器来生成——例如“int("100")”将生成一个整数“100”(如果不带参数则是生成整数“0”)。所有对象设置完成之后执行mainloop()函数将启动程序的“主事件循环”,显示定义好的图形界面并开始用户交互——对于这个最简单的程序来说,你可以进行默认的窗口操作:移动、缩放、最小化、最大化和关闭等等。

其他常用的可视化部件有“标签”(Label)、“按钮”(Button)、“输入框”(Entry)、“文本区”(Text)等等,这些部件都不能独立存在而是从属于窗口这样的“容器”,你可以使用特定的布局方法例如pack()把它们放进容器对象,默认从上到下放置:

label = tk.Label(window, text="测试标签")
label.pack()
button = tk.Button(window, text="测试按钮")
button.pack(side="bottom")  # 放到容器底部
entry = tk.Entry(window, width=50)  # 输入框宽50字符
entry.pack()
text = tk.Text(window, width=50, height=12, background="wheat")  # 文本区宽50字符高12字符,麦色背景
text.pack()

使用网格布局方法grid()可以在同一行放置多个部件,但此方法不可与pack()同时使用。还有一种定位布局方法place()指定部件在容器中的绝对坐标(原点在左上角,x轴向右,y轴向下),以下代码改用grid()和place()调整窗口布局:

label = tk.Label(window, text="测试标签")
label.grid(row=0, column=0)  # 标签放在0行0列
button = tk.Button(window, text="测试按钮")
button.grid(row=0, column=1)  # 按钮放在0行1列
entry = tk.Entry(window, width=50)
entry.grid(row=1, column=0, columnspan=2, padx=20, pady=10)  # 输入框在1行0列,横跨两列,横向留空20像素,纵向留空10像素
text = tk.Text(window, width=50, height=12, background="wheat")
text.place(x=20, y=100)  # 文本区放在指定的坐标

在生成部件对象时可以设置对象事件的处理函数,实现各种“人机交互”功能——让我们继续改进程序,为按钮对象加入点击事件的处理函数,把你在输入框输入的文本添加到文本区的现有文本中:

"""tktest.pyw 实现按钮点击事件处理
"""
import tkinter as tk


def change(widget, var):
    """事件处理函数:改变Text部件的文本
    在widget现有文本末尾插入新的文本var
    """
    widget.config(state="normal")
    widget.insert("end", var + "\n")
    widget.config(state="disabled")


def main():
    """主函数:设置窗口部件,指定按钮点击事件处理函数
    """
    window = tk.Tk()
    window.geometry("400x300")
    window.title("简单图形界面程序")
    label = tk.Label(window, text="请输入文本并点击添加")
    label.grid(row=0, column=0)
    entry = tk.Entry(window, width=50)
    entry.grid(row=1, column=0, columnspan=2, padx=20, pady=10)
    text = tk.Text(window, width=50, height=12, background="wheat")
    text.config(state="disabled")
    text.place(x=20, y=100)
    button = tk.Button(window, text="添加",
                       command=lambda: change(text, entry.get()))
    button.grid(row=0, column=1)
    tk.mainloop()


if __name__ == "__main__":
    main()

接下来的示例是一个图片查看器——显示图片需要配合使用“画布”(Canvas)和“图像”(PhotoImage)部件(tkinter支持的图片格式有PNG和GIF等),这个程序还引入了tkinter包中的另一个模块filedialog以便显示标准的打开文件对话框:

"""tkimage.pyw 简单的图片查看器
"""
import tkinter as tk
import tkinter.filedialog as fd


def openimage(canvas):
    """事件处理函数:使用文件对话框打开图片
    """
    filename = fd.askopenfilename(filetypes=[("PNG图片", "*.png"),
                                             ("GIF图片", "*.gif")])
    global image  # 注意这个需要定义为全局变量
    image = tk.PhotoImage(file=filename)
    canvas.create_image((0, 0), image=image, anchor="nw")


def main():
    """主函数:设置窗口部件,指定按钮点击事件处理函数
    """
    window = tk.Tk()
    window.geometry("600x480")
    window.title("简单的图片查看器")
    canvas = tk.Canvas(window, width=600, height=440)
    canvas.pack(side="bottom")
    button = tk.Button(window, text="打开图片",
                       command=lambda: openimage(canvas))
    button.pack()
    tk.mainloop()


if __name__ == "__main__":
    main()
10_image.png

这个图片查看器确实很简单,你可以尝试继续改进……有关tkinter的详情可以查看官方文档 https://docs.python.org/3.6/library/tkinter.html

——编程原来是这样……

编程小提示

你已经看到tkinter所支持的图像功能和文件格式非常有限,如果你需要处理JPG等其他常用图片文件格式,可以安装第三方包“pillow”(Python Imaging Library,简称PIL)——注意:软件包名是pillow而模块名是PIL:

from PIL import Image, ImageTk

# image = tk.PhotoImage(file=filename)  这一句改为下面这两句
image = Image.open(filename)
image = ImageTk.PhotoImage(image)

canvas.create_image((0, 0), image=image, anchor="nw")

修改后的程序就可以打开几乎任何格式的图片了,有关pillow的详情可以查看发布页面 https://pypi.python.org/pypi/Pillow/5.1.0

下一篇:编程入门11:Python面向对象

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,012评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,628评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,653评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,485评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,574评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,590评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,596评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,340评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,794评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,102评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,276评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,940评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,583评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,201评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,441评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,173评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,136评论 2 352

推荐阅读更多精彩内容