跳至主要内容

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()








评论

此博客中的热门博文

自动发送消息

  # https://pyperclip.readthedocs.io/en/latest/ import pyperclip while True :     # pyperclip.copy('Hello, world!')     # pyperclip.paste()     # pyperclip.waitForPaste()     print ( pyperclip. waitForNewPaste ( ) )     # 获取要输入新的坐标,也可以通过autohotkey import time import pyautogui  as pag import os   try :     while True :         print ( "Press Ctrl-C to end" )         x , y = pag. position ( )   # 返回鼠标的坐标         posStr = "Position:" + str ( x ) . rjust ( 4 ) + ',' + str ( y ) . rjust ( 4 )         print ( posStr )   # 打印坐标         time . sleep ( 0.2 )         os . system ( 'cls' )   # 清楚屏幕 except KeyboardInterrupt :     print ( 'end....' )     # 打印消息 import pyautogui import time import pyperclip   content = """   呼叫龙叔! 第二遍! 第三遍! 第四遍...

学习地址

清华大学计算机系课程攻略 https://github.com/PKUanonym/REKCARC-TSC-UHT 浙江大学课程攻略共享计划 https://github.com/QSCTech/zju-icicles https://home.unicode.org/ 世界上的每个人都应该能够在手机和电脑上使用自己的语言。 http://codecanyon.net   初次看到这个网站,小伙伴们表示都惊呆了。原来代码也可以放在网上卖的?!! 很多coder上传了各种代码,每个代码都明码标价。看了下销售排行,有的19刀的卖了3万多份,额di神啊。可以看到代码的演示效果,真的很漂亮。代码以php、wordpress主题、Javascript、css为主,偏前台。 https://www.lintcode.com/ 算法学习网站,上去每天刷两道算法题,走遍天下都不怕。 https://www.codecademy.com/ 包含在线编程练习和课程视频 https://www.reddit.com/ 包含有趣的编程挑战题,即使不会写,也可以查看他人的解决方法。 https://ideone.com/ 在线编译器,可运行,可查看代码示例。 http://it-ebooks.info/ 大型电子图书馆,可即时免费下载书籍。 刷题 https://github.com/jackfrued/Python-100-Days https://github.com/kenwoodjw/python_interview_question 面试问题 https://github.com/kenwoodjw/python_interview_question https://www.journaldev.com/15490/python-interview-questions#python-interpreter HTTP 身份验证 https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Authentication RESTful 架构详解 https://www.runoob.com/w3cnote/restful-architecture.html https://www.rosettacode.org/wiki/Rosetta_C...

mysql 入门

资料 https://dinfratechsource.com/2018/11/10/how-to-install-latest-mysql-5-7-21-on-rhel-centos-7/ https://dev.mysql.com/doc/refman/5.7/en/linux-installation-yum-repo.html https://www.runoob.com/mysql/mysql-create-database.html https://www.liquidweb.com/kb/install-java-8-on-centos-7/ 工具 https://www.heidisql.com/ HeidiSQL是免费软件,其目标是易于学习。 “ Heidi”使您可以从运行数据库系统MariaDB,MySQL,Microsoft SQL或PostgreSQL的计算机上查看和编辑数据和结构 MySQL 连接时尽量使用 127.0.0.1 而不是 localhost localhost 使用的 Linux socket,127.0.0.1 使用的是 tcp/ip 为什么我使用 localhost 一直没出问题 因为你的本机中只有一个 mysql 进程, 如果你有一个 node1 运行在 3306, 有一个 node2 运行在 3307 mysql -u root -h localhost -P 3306 mysql -u root -h localhost -P 3307 都会连接到同一个 mysql 进程, 因为 localhost 使用 Linux socket, 所以 -P 字段直接被忽略了, 等价于 mysql -u root -h localhost mysql -u root -h localhost 而 -h 默认是 localhost, 又等价于 mysql -u root mysql -u root 为了避免这种情况(比如你在本地开发只有一个 mysql 进程,线上或者 qa 环境有多个 mysql 进程)最好的方式就是使用 IP mysql -u root -h 127 .0 .0 .1 -P 3307 strac...