跳至主要内容

tkinter 入门

查看tkinter版本
方法一:
cmd直接输入
python -m tkinter

方法二:
cmd输入python
>>> import tkinter
>>> tkinter._test()
>>> tkinter.Tcl().eval('info patchlevel')




参考资料
https://www.geeksforgeeks.org/python-gui-tkinter/
https://likegeeks.com/python-gui-examples-tkinter-tutorial/
http://www.openbookproject.net/courses/python4fun/tkphone1.html

tkinter框架

#导入(调用)tkinter模块
from tkinter import *

#创建Tk()的对象,它实际上用于创建窗口
my_window = Tk()

#调用mainloop()函数,用于窗口的无限循环。当我们点击关闭按钮或退出应用程序时,mainloop()函数终止
my_window.mainloop()

print(id(my_window), type(my_window),dir(my_window))
输出 53949680
<class 'tkinter.Tk'>
['_Misc__winfo_getint', '_Misc__winfo_parseitem', '__class__',...]

#遍历
for key in root.keys():
    print(key,":",root[key])

设置窗口标题

my_window.title("Demo")

更改左上角图标

my_window.iconbitmap(r'C:\src\dragon-face.ico')

from pathlib import Path
my_window.iconbitmap(Path('img/dragon.ico').absolute())

设置窗口背景颜色

#用16进制红绿蓝表示,共256 x 256 x256 = 16777216种
#颜色网站https://www.color-hex.com/
#https://encycolorpedia.com/
my_window.configure(background='red')
my_window.configure(bg='#ff0000')


设置窗口大小

my_window.configure(width=400, height=200, background='#94d42b')

窗口宽高是否可变

#True:可变  False:不可变
my_window.resizable(width=True, height=False)



设置窗口位置

#widthxheight+x+y
#电脑屏幕左上角坐标位置 x=0,y=0
#geometry(几何图形)的width(宽)、height(高) 优先于 configure(配置)
my_window.geometry("500x300+800+100")


窗口放在屏幕最中间

#窗口宽度、高度
width_of_window = 800
height_of_window = 600

#电脑屏幕宽度、高度,也就是屏幕分辨率
screen_width = my_window.winfo_screenwidth()
screen_height = my_window.winfo_screenheight()

#x、y坐标(coordinate)
x_coordinate = (screen_width/2) - (width_of_window/2)
y_coordinate = (screen_height/2) - (height_of_window/2)

#窗口位于屏幕正中间的三个方法
my_window.geometry("%dx%d+%d+%d" % (width_of_window, height_of_window, x_coordinate, y_coordinate))

my_window.geometry("{}x{}+{}+{}".format(width_of_window, height_of_window, int(x_coordinate), int(y_coordinate)))

my_window.geometry(f"{width_of_window}x{height_of_window}+{int(x_coordinate)}+{int(y_coordinate)}")


首先必须将小部件与所谓的几何管理器(geometry)放在一起。两个最常见的是包(pack)和网格(grid),才能显示在窗口,注意pack和grid不能在一个框架内混用
还有一种place(放置)方法可以将窗口小部件定位在框架或窗口内的精确位置。并不经常使用

使用包或网格时,还有其他常用的关键字参数。我们看到上面的padx和pady。对于网格,有一个sticky(粘性)参数,它采用N,E,S,W,NE等地图坐标。如果网格单元格大于您的小部件,因为较大的小部件位于同一行或列中,粘性有助于您将小部件放在单元格中的所需位置

小部件是对象并具有方法
创建窗口小部件时可以传递的任何关键字参数也可以传递给它的configure(配置)方法

标签(Label)小部件介绍


#用于在Tk()窗口中显示文本或图像#显示文本
label_1 = Label(my_window, text='标签1')
label_2 = Label(my_window, text='标签2')



# 默认按side=TOP顺序自上而下排列标签 还有参数(TOP,LEFT,RIGHT,BOTTOM))
# pack方法告诉Tk使窗口的大小适合给定的文本
#“padx”在左右两侧添加像素,“pady”将像素添加到顶部和底部label_2.pack(side = LEFT , padx=10)
label_1.pack(side = LEFT, padx=10)

#显示图像
img = PhotoImage(file="python-logo.png")

#这两行代码用于在窗口上创建和显示图像
#第一行创建具有两个参数的Label类的对象,第一个参数是父窗口的对象,第二个参数指定要在标签上显示的图像
label_1 = Label(my_window, image=img)
#第二行控制窗口中Label的表示,grid()指定屏幕上的行号和列号。row = 0和column = 0引导tkinter在屏幕的最左上角显示标签
label_1.grid(row=0, column=0)

设置标签背景颜色、字体类型、字体颜色、大小

label_1 = Label(my_window, text="标签1", bg="blue", fg="white", font="Times 30 italic bold")

#设置鼠标接近和离开标签时,text字体变色
#绑定(bind)事件(event)
from functools import partial
def color_config(widget, color, event):
    widget.configure(foreground=color)

label_1.bind("<Enter>", partial(color_config, label_1, "red"))
label_1.bind("<Leave>", partial(color_config, label_1, "#daa520"))

label_1.pack()
#参考https://stackoverflow.com/questions/29594019/italicize-tkinter-label-text-on-focus


设置标签宽度

#width是标签宽度,不是text宽度
label_1 = Label(my_window, text="标签1", bg="blue", fg="white", font="Times 30 italic bold", width=20)
label_2 = Label(my_window, text="标签2", bg="red", fg="white", font="Times 30 italic bold", width=30)
label_1.pack()
label_2.pack()


设置标签高度

#text两行,height=3代表3个字符高度,则text放中间位置
label_1 = Label(my_window,
                text="标签1\nsolid",
                bd=1,
                relief="solid",
                height=3)


标签中多行内容展示

#换行用\n,换n行用n个\n
label_1 = Label(my_window, text="标签1\n换一行\n\n换两行\n", bg="blue", fg="white", font="Times 30 italic bold", width=20)

设置标签边框宽度(borderwidth或者bd)

#浮雕(relief[flat,groove,raised,sunken,ridge,solid])
label_1 = Label(my_window, text="标签1 flat", borderwidth=12, relief="flat")
label_2 = Label(my_window, text="标签2 groove", bd=12, relief="groove")
label_3 = Label(my_window, text="标签3 raised", bd=12, relief="raised")
label_4 = Label(my_window, text="标签4 sunken", bd=12, relief="sunken")
label_5 = Label(my_window, text="标签5 ridge", bd=12, relief="ridge")
label_6 = Label(my_window, text="标签6 solid", bd=16, relief="solid")


定义标签中text内容的位置

#锚(anchor)可以确定text在标签中的位置,要求大写
#N、NE、E、SE、S、SW、W、NW、CENTER
#北、东北、东、东南、南、西南、西、西北、中心
my_window.geometry("400x250")
label_1 = Label(my_window,
                text="标题")
label_2 = Label(my_window,
                text="这是\n内容",
                bd=1,
                relief="solid",
                width=15,
                height=4,
                anchor=CENTER)

标签中内容对齐方式

#justify:text中的内容对齐,LEFT、RIGHT、CENTER
label_1 = Label(my_window,
                text="这\n是内\n容展示",
                bd=1,
                relief="solid",
                font="Times 20",
                anchor=CENTER,
                justify=LEFT)

定义标签中内容位置及对齐方式

#anchor代表在标签label中的位置
#justify代表文本text对齐方式
label_2 = Label(my_window,
                text="这\n是内\n容展示",
                bd=1,
                relief="solid",
                font="Times 20",
                width=15,
                height=6,
                anchor=SW,
                justify=LEFT)

填充标签内容周围的空间

#用padx、pady填充标签文本周围的空间
label_1 = Label(my_window,
                text="标题",
                bd=1,
                relief="solid",
                padx=20,
                pady=20)
         

查找标签值

print(label_1['text'])

更改标签值

label_1['text']=“新的内容”

访问标签键值

#健列表
print(label_1.keys())
#键:值
for item in label_1.keys():
    print(item, ":", label_1[item])


标签中的textvariable使用

var_1 = StringVar()

label_1 = Label(my_window, textvariable=var_1)
label_2 = Label(my_window)

label_1.pack()
label_2.pack()

var_1.set("你好")
label_2["text"] = "你好"

按钮(Button)小部件介绍

参数:
activebackground:设置按钮按下时的背景颜色
activeforeground:设置按钮按下时的前景色
bg:设置背景颜色
command:调用函数
font:设置按钮标签上的字体
image:在按钮上设置图像
width:设置按钮的宽度
height:设置按钮的高度

def add_label():
    label_1 = Label(my_window, text='你好')
    label_1.pack()

button_1 = Button(my_window,
                  text='添加标签',
                  command=add_label)

button_1.pack()


网格几何图形管理器Grid Geometry Manager

#利用width,height定义宽高
label_1 = Label(my_window,width=20,height=8,bg="red")
button_1 = Button(my_window,text="打开")

label_1.grid(row=0,column=0)
button_1.grid(row=1,column=0)


输入(Entry)小部件


def say_hello():
    var_1.set("hello:" + var_2.get())
    #print(type(var_2.get()))可知返回的是str类型

var_1 = StringVar()
var_2 = StringVar()

label_1 = Label(my_window, text="请输入名字:")
entry_1 = Entry(my_window, textvariable=var_2)
button_1 = Button(my_window, text="问候", command=say_hello)
label_2 = Label(my_window, textvariable=var_1)

label_1.grid(row=0, column=0)
entry_1.grid(row=0, column=1)
button_1.grid(row=1, column=0)
label_2.grid(row=1, column=1)

#聚焦输入方法一、二
entry_1.focus()
entry_1.focus_force()

继承框架(Frame)用法

class RedFrame(Frame):
    def __init__(self,the_window):
        super().__init__()
        self["width"]=150
        self["height"]=150
        self["relief"]=RAISED
        self["bd"]=8
        self["bg"]="red"

frame_1=RedFrame(my_window)
frame_1.grid(row=0,column=0)


画布(Canvas)中用随机颜色画线


参数
bd:设置边框宽度(以像素为单位)
bg:设置正常的背景颜色
cursor:设置画布中使用的光标
highlightcolor:设置focus_force()时高亮显示的颜色
width:设置窗口小部件的宽度
height:设置小部件的高度

from random import *
def random_color_code():
    hex_charx = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']
    colour_code = '#' + ''.join([choice(hex_charx) for i in range(0,6)])
    return colour_code

my_canvas = Canvas(my_window, width=400, height=400, bg=random_color_code())
my_canvas.grid(row=0, column=0)

for i in range(0, 1000):
    x1 = randint(0, 400)
    y1 = randint(0, 400)
    x2 = randint(0, 400)
    y2 = randint(0, 400)
    width_random = randint(1, 20)

    #create_line用法起点x1,y1 终点x2,y2
    my_canvas.create_line(x1, y1, x2, y2, fill=f'#{randint(0,0xffffff):06x}', width=width_random)
    my_canvas.update()


画布中用线画图形

#多笔画法
my_canvas.create_line(100, 100, 300, 100, fill="blue", width=5)
my_canvas.create_line(300, 100, 350, 300, fill="blue", width=5)
my_canvas.create_line(350, 300, 50, 300, fill="blue", width=5)
my_canvas.create_line(50, 300, 100, 100, fill="blue", width=5)

#一笔画法,连接处闭合
my_canvas.create_line(100, 100, 300, 100, 200, 300, 100, 100, fill="red", width=5)


画布中的箭头arrow

#箭头arrow走向有first,last,both,none默认为nonemy_canvas.create_line(100, 100, 300, 100, fill="blue", arrow="first", width=5)


#箭头形状有arrowshape=(a,b,c)确定
#a水平值,c垂直值的一半,b垂直与水平交点到顶点
my_canvas.create_line(500, 100, 700, 100, fill="red", arrow="last", arrowshape=(30, 45, 28), width=5)



Text小部件

from tkinter import *
from pathlib import Path

my_window = Tk()
text = Text(my_window,height=3)

text.insert(INSERT, "Hello.....")

text.insert(END, "Bye Bye.....")

text.pack(side=TOP)



text.tag_add("here", "1.0", "1.4")

text.tag_add("start", "1.8", "1.13")

text.tag_config("here", background="yellow", foreground="blue")

text.tag_config("start", background="black", foreground="green")

text1 = Text(my_window, height=25, width=30)
photo = PhotoImage(file=Path('guido.gif').absolute())
text1.insert(END, '\n')
text1.image_create(END, image=photo)

text1.pack(side=LEFT)

text2 = Text(my_window, height=25, width=50)
scroll = Scrollbar(my_window, command=text2.yview)
text2.configure(yscrollcommand=scroll.set)
text2.tag_configure('bold_italics', font=('Arial', 12, 'bold', 'italic'))
text2.tag_configure('big', font=('Verdana', 20, 'bold'))
text2.tag_configure('color',
                    foreground='#476042',
                    font=('Tempus Sans ITC', 12, 'bold'))
text2.tag_bind('follow',
               '<1>',
               lambda e, t=text2: t.insert(END, "Not now, maybe later!"))
text2.insert(END,'\nThe Zen of Python\n', 'big')
quote = """
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
"""
text2.insert(END, quote, 'color')
text2.insert(END, 'follow-up\n', 'follow')
text2.pack(side=LEFT)
scroll.pack(side=RIGHT, fill=Y)

my_window.mainloop()


对话框filedialog

try:
    import tk as tk
    import tc as tc
    import tf as tm
except:
    import tkinter as tk
    import tkinter.constants as tc
    import tkinter.filedialog as tf


class tfExample(tk.Frame):
    def __init__(self, root):
        tk.Frame.__init__(self, root)

        # options for buttons
        button_opt = {'fill': tc.BOTH, 'padx': 5, 'pady': 5}

        # define buttons
        tk.Button(self, text='askopenfile', command=self.askopenfile).pack(**button_opt)
        tk.Button(self, text='askopenfilename', command=self.askopenfilename).pack(**button_opt)
        tk.Button(self, text='asksaveasfile', command=self.asksaveasfile).pack(**button_opt)
        tk.Button(self, text='asksaveasfilename', command=self.asksaveasfilename).pack(**button_opt)
        tk.Button(self, text='askdirectory', command=self.askdirectory).pack(**button_opt)

        # define options for opening or saving a file
        self.file_opt = options = {}
        options['defaultextension'] = '.txt'
        options['filetypes'] = [('all files', '.*'), ('text files', '.txt')]
        options['initialdir'] = 'C:\\'
        options['initialfile'] = 'myfile.txt'
        options['parent'] = root
        options['title'] = 'This is a title'

        # This is only available on the Macintosh, and only when Navigation Services are installed.
        # options['message'] = 'message'

        # if you use the multiple file version of the module functions this option is set automatically.
        # options['multiple'] = 1

        # defining options for opening a directory
        self.dir_opt = options = {}
        options['initialdir'] = 'C:\\'
        options['mustexist'] = False
        options['parent'] = root
        options['title'] = 'This is a title'

    def askopenfile(self):

        """Returns an opened file in read mode."""

        return tf.askopenfile(mode='r', **self.file_opt)

    def askopenfilename(self):

        """Returns an opened file in read mode.
        This time the dialog just returns a filename and the file is opened by your own code.
        """

        # get filename
        filename = tf.askopenfilename(**self.file_opt)

        # open file on your own
        if filename:
            return open(filename, 'r')

    def asksaveasfile(self):

        """Returns an opened file in write mode."""

        return tf.asksaveasfile(mode='w', **self.file_opt)

    def asksaveasfilename(self):

        """Returns an opened file in write mode.
        This time the dialog just returns a filename and the file is opened by your own code.
        """

        # get filename
        filename = tf.asksaveasfilename(**self.file_opt)

        # open file on your own
        if filename:
            return open(filename, 'w')

    def askdirectory(self):

        """Returns a selected directoryname."""

        return tf.askdirectory(**self.dir_opt)


if __name__ == '__main__':
    root = tk.Tk()
    tfExample(root).pack()
    root.mainloop()








评论

此博客中的热门博文

Mongo 入门

https://pymongo.readthedocs.io/en/stable/tutorial.html https://www.mongodb.com/languages/python https://zhuanlan.zhihu.com/p/51171906 https://www.runoob.com/python3/python-mongodb.html https://blog.baoshuo.ren/post/luogu-spider/ https://hub.docker.com/_/mongo 安装 MongoDB $ docker search mongo 启动一个mongo服务器实例 $ docker run --name some-mongo -d mongo:tag some-mongo是您要分配给容器的名称,tag是指定您想要的 MongoDB 版本的标签 MongoDB 的默认数据目录路径是/data/db 如下: $ docker run -it -v mongodata:/data/db -p 27017:27017 --name mongodb --restart unless-stopped -d mongo 你应该让 MongoDB 在端口 27017 上运行,并且可以通过localhostWindows 和 Ubuntu 20.04 上的URL访问 http://localhost:27017/ -p 是 HOST_PORT:CLIENT_PORT  -P 随机端口 -p 27017:27017 :将容器的27017 端口映射到主机的27017 端口 -v mongodata:/data/db :将主机中当前目录下的db挂载到容器的/data/db,作为mongo数据存储目录 从另一个 Docker 容器连接到 MongoDB 镜像中的 MongoDB 服务器侦听标准 MongoDB 端口27017,因此通过 Docker 网络连接将与连接到远程mongod. 以下示例启动另一个 MongoDB 容器实例,并mongo针对上述示例中的原始 MongoDB 容器运行命令行客户端,从而允许您针对数据库实例执行 MongoDB 语句: $ docker run -it --network some-network --...

MechanicalSoup

用于自动与网站交互的 Python 库。 MechanicalSoup 自动存储和发送 cookie,跟踪重定向,并且可以跟踪链接和提交表单。 它不执行 JavaScript。 https://github.com/MechanicalSoup/MechanicalSoup https://mechanicalsoup.readthedocs.io/en/stable/index.html https://realpython.com/python-web-scraping-practical-introduction/ pip show Mechanicalsoup 找到模块的安装位置 https://stackoverflow.com/questions/54352162/download-file-with-mechanicalsoup # Install dependencies # pip install requests # pip install BeautifulSoup4 # pip install MechanicalSoup # Import libraries import mechanicalsoup import urllib.request import requests from bs4 import BeautifulSoup import re # Create a browser object that can collect cookies browser = mechanicalsoup.StatefulBrowser() browser.open("https://www.ons.gov.uk/economy/grossdomesticproductgdp/timeseries/l2kq/qna") browser.download_link(link_text=".xls",file="D:/ONS_Data.xls" )

端口映射 公网访问内网

https://portforward.com/ Holer 通过安全隧道将位于NAT和防火墙之后的本地服务器暴露给公共Internet。 Holer是一个将原型中的应用映射到公网访问的端口映射软件,支持转发基于TCP协议的报文 https://github.com/wisdom-projects/holer 方式一:使用(公告)的holer映射或者开通holer服务,通过holer客户端软件经 holer服务器实现公网访问。 公开的holer映射详情如下: 访问密钥 访问域名 公网地址 本地地址 使用场景 HOLER_CLIENT-2F8D8B78B3C2A0AE holer65530.wdom.net holer.org:65530 127.0.0.1:8080 网页 HOLER_CLIENT-3C07CDFD1BF99BF2 holer65531.wdom.net holer.org:65531 127.0.0.1:8088 网页 HOLER_CLIENT-2A623FCB6E2A7D1D holer65532.wdom.net holer.org:65532 127.0.0.1:80 网页 HOLER_CLIENT-AF3E6391525F70E4 不适用 holer.org:65533 127.0.0.1:3389 远程桌面 HOLER_CLIENT-822404317F9D8ADD 不适用 holer.org:65534 127.0.0.1:22 SSH协议 HOLER_CLIENT-27DD1389DF1D4DBC 不适用 holer.org:65535 127.0.0.1:3306 数据库 使用Java版本的holer客户端 ①java 1.7或者更高版本 ②下载holer-client.zip 修改配置文件C:\holer-client\conf\holer.conf HOLER_ACCESS_KEY=HOLER_CLIENT-2A623FCB6E2A7D1D HOLER_SERVER_HOST=holer65532.wdom.net ③建议先双击运行C:\holer-client\bin\shutdown.bat,再双击运行C:\holer-client\bin\startup.bat...