Introduction
It is often necessary to write some scripts, configure some parameters and start calculations, and hope to make it accessible to others, and will execute it in a visual manner
Mainly use the tkinter library, in terms of layout, you can construct a Frame per line and pack it to the window. Frames in each line can be laid out by pack or grid or place. By analogy, multiple controls can be extended
Simple workflow
Each button control of the window will generate events, and then generally call back functions, but it is blocked in the main thread to call back. It is impossible for us to create threads to execute asynchronously every time, so we use a message queue to decouple button events And the callback processing function, the message of the original queue is consumed by the consumer to directly determine the message type consumption, but for the sake of code brevity, it is handed over to another class for processing.
effect
Source code
Perform custom calculations in the start_demo function
import queue
import threading
import time
import traceback
from tkinter import Tk, Button, messagebox, Label, Frame, LEFT, Entry, IntVar, Radiobutton, StringVar, Checkbutton, \
BooleanVar, RIGHT, constants, Scale, HORIZONTAL, Variable, filedialog, Text, font, Scrollbar
from tkinter. font import Font, BOLD
from tkinter. messagebox import showinfo, showerror, showwarning
from tkinter. ttk import Combobox, Widget
from enum import Enum
from import GuiTempldate
class MsgEnum ( Enum) :
"""
消息类型枚举
"""
START = 0
STOP = 1
EXIT = 3
def start_demo ( gui: GuiTempldate) :
""" 自定义计算任务
:param gui: gui组件对象
:return:
"""
count = 20
while gui. Cache. RUNING:
count -= 1
gui. text_btn. insert( constants. END, f"cd {count}\n" )
gui. text_btn. see( constants. END)
time. sleep( 1 )
class GuiTempldate :
class Cache :
RUNING = False
def __init__ ( self) - > None :
self. msg_center = MsgCenter( self)
self. root = Tk( )
self. root. title( "xxx工具" )
self. root. geometry( '500x600+500+200' )
self. root. protocol( "WM_DELETE_WINDOW" , self. close_event)
self. url_var = None
self. url_btn = None
self. mode_var = None
self. name_var = None
self. name_btn = None
self. is_xx_btn = None
self. is_xx_var = None
self. level_var = None
self. scale_btn = None
self. start_btn = None
self. stop_btn = None
self. select_file_var = None
self. text_btn = None
self. initGui( )
def initGui ( self) :
text_str = """版本: 2.0.1
#author burukeyou
#说明:
1) 这是关于
2) 请先开始再停止"""
Label( self. root, text= text_str, justify= 'left' , fg= 'red' ) . pack( anchor= constants. W)
Label( self. root, text= '请求接口' ) . pack( anchor= constants. W)
self. url_var = StringVar( value= "http://www.baidu.com" )
self. url_btn = Entry( self. root, width= 60 , textvariable= self. url_var)
self. url_btn. pack( anchor= constants. W)
self. mode_var = IntVar( value= 1 )
fm01 = Frame( self. root)
fm01. pack( anchor= constants. W)
Label( fm01, text= '模式' ) . grid( row= 0 , column= 0 , sticky= 'W' )
Radiobutton( fm01, text= 'a模式' , variable= self. mode_var, value= 1 ) . grid( row= 0 , column= 1 , sticky= 'E' , padx= 40 )
Radiobutton( fm01, text= 'b模式' , variable= self. mode_var, value= 2 ) . grid( row= 0 , column= 2 , sticky= 'E' , padx= 40 )
Radiobutton( fm01, text= 'c模式' , variable= self. mode_var, value= 3 ) . grid( row= 0 , column= 3 , sticky= 'E' , padx= 40 )
fm02 = Frame( self. root)
self. name_var = StringVar( value= 100 )
fm02. pack( anchor= constants. W, fill= constants. X)
Label( fm02, text= '名字 ' ) . pack( side= constants. LEFT)
self. name_btn = Entry( fm02, width= 20 , textvariable= self. name_var)
self. name_btn. pack( side= constants. RIGHT)
self. is_xx_var = BooleanVar( )
self. is_xx_btn = Checkbutton( self. root, variable= self. is_xx_var, text= '是否xxx' , onvalue= True , offvalue= False )
self. is_xx_btn. pack( anchor= constants. W)
fm03 = Frame( self. root)
fm03. pack( anchor= constants. W, fill= constants. X)
self. level_var = StringVar( )
Label( fm03, text= '统计级别 ' ) . pack( side= constants. LEFT)
com = Combobox( fm03, textvariable= self. level_var)
com. pack( side= constants. RIGHT)
com[ "value" ] = ( "级别0" , "级别1" , "级别2" )
com. current( 1 )
fm04 = Frame( self. root)
fm04. pack( anchor= constants. W, fill= constants. X)
Label( fm04, text= '范围: ' ) . pack( side= constants. LEFT)
self. scale_btn = Scale( fm04, from_= 0 , to= 100 , orient= constants. HORIZONTAL, tickinterval= 100 , length= 200 )
self. scale_btn. pack( side= constants. RIGHT)
self. scale_btn. set ( 20 )
fm05 = Frame( self. root)
fm05. pack( anchor= constants. W, fill= constants. X)
self. select_file_var = StringVar( value= "你没有选择任何文件" )
Button( fm05, text= "选择处理的文件" , command= self. click_file_event) . pack( side= constants. LEFT)
Label( fm05, textvariable= self. select_file_var) . pack( side= constants. RIGHT)
fm22 = Frame( self. root)
fm22. pack( anchor= constants. W, fill= constants. X)
scroll = Scrollbar( fm22)
scroll. pack( side= constants. RIGHT, fill= constants. Y)
ft = Font( family= '微软雅黑' , size= 18 , weight= font. BOLD)
self. text_btn = Text( fm22, height= 9 , fg= "green" , font= ft, bg= "black" , insertbackground= "red" )
self. text_btn. pack( side= constants. LEFT)
scroll. config( command= self. text_btn. yview)
self. text_btn. config( yscrollcommand= scroll. set )
fm06 = Frame( self. root)
self. start_btn = Button( fm06, text= "开始" , width= 6 , height= 1 , command= self. start_event)
self. start_btn. grid( row= 0 , column= 0 , sticky= 'W' , padx= 20 , pady= 20 )
self. stop_btn = Button( fm06, text= "停止" , width= 6 , height= 1 , command= self. stop_event)
self. stop_btn. grid( row= 0 , column= 1 , sticky= 'E' , padx= 20 , pady= 20 )
fm06. pack( side= constants. BOTTOM)
def start_event ( self) :
self. msg_center. put( MsgEnum. START)
self. Cache. RUNING = True
threading. Thread( target= start_demo, args= ( self, ) ) . start( )
def stop_event ( self) :
self. msg_center. put( MsgEnum. STOP)
self. Cache. RUNING = False
def click_file_event ( self) :
filename = filedialog. askopenfilename( )
if filename != '' :
self. select_file_var. set ( filename)
print ( self. select_file_var. get( ) )
def close_event ( self) :
if self. Cache. RUNING and not messagebox. askokcancel( "警告" , "任务还在执行中,确定要关闭吗?" ) :
return
self. root. destroy( )
self. msg_center. put( MsgEnum. EXIT)
def showUI ( self) :
threading. Thread( target= self. msg_center. mainloop) . start( )
self. root. mainloop( )
class MsgCenter :
"""
消息队列
主要处理窗口控件消息
"""
def __init__ ( self, obj: GuiTempldate) - > None :
self. queue = queue. Queue( )
self. obj = obj
def put ( self, msg: Enum) :
self. queue. put( msg)
def mainloop ( self) :
while True :
try :
msg = self. queue. get( )
print ( "消费消息: {}" . format ( msg) )
if msg == MsgEnum. START:
MsgStrategy. start_strategy( self. obj)
elif msg == MsgEnum. STOP:
MsgStrategy. stop_strategy( self. obj)
elif msg == MsgEnum. EXIT:
break
else :
pass
except queue. Empty:
traceback. print_exc( )
class MsgStrategy :
@classmethod
def start_strategy ( cls, gui: GuiTempldate) :
gui. start_btn. config( state= constants. DISABLED)
gui. stop_btn. config( state= constants. NORMAL)
gui. is_xx_btn. config( state= constants. DISABLED)
gui. scale_btn. config( state= constants. DISABLED)
gui. url_btn. config( state= constants. DISABLED)
gui. name_btn. config( state= constants. DISABLED)
val = f"""
接口:[{gui.url_var.get()}]
模式:[{gui.mode_var.get()}]
名字:[{gui.name_var.get()}]
是否xx: [{gui.is_xx_var.get()}]
统计级别:[{gui.level_var.get()}]
范围: [{gui.scale_btn.get()}]
文件: [{gui.select_file_var.get()}]
"""
showinfo( "" , val)
@classmethod
def stop_strategy ( cls, gui: GuiTempldate) :
gui. start_btn. config( state= constants. NORMAL)
gui. stop_btn. config( state= constants. DISABLED)
gui. is_xx_btn. config( state= constants. NORMAL)
gui. scale_btn. config( state= constants. NORMAL)
gui. url_btn. config( state= constants. NORMAL)
gui. name_btn. config( state= constants. NORMAL)
if __name__ == '__main__' :
gui = GuiTempldate( )
gui. showUI( )
Reward
If you find the article useful, you can encourage the author