通过前面学习的 Tkinter 知识,这一节我们将《垃圾邮件识别器》所需要的界面搭建起来,界面主要包括:
- 主窗口
- 顶部菜单
- 中心文本框
- 底部状态栏
1. 主窗口

创建 MainFrame.py 文件,创建 MainFrame 类如下:
import tkinter as tk
class MainFrame(tk.Tk):
def __init__(self):
# 初始化父类
super(MainFrame, self).__init__()
# 定义窗口宽高
self.window_w, self.window_h = 800, 500
# 获得屏幕尺寸
screen_w, screen_h = self.winfo_screenwidth(), self.winfo_screenheight()
# 计算窗口屏幕中心位置
start_x, start_y = int(screen_w / 2 - self.window_w / 2), int(screen_h / 2 - self.window_h / 2)
# 设置屏幕尺寸以及初始位置
self.geometry(f'{self.window_w}x{self.window_h}+{start_x}+{start_y}')
# 设置窗口标题
self.title('垃圾邮件识别器')
# 初始化其他窗口
self.init_widgets()
def init_widgets(self):
pass
def show(self):
self.mainloop()
创建程序入口文件 App.py,其中代码如下:
from MainFrame import MainFrame
if __name__ == '__main__':
main_frame = MainFrame()
main_frame.show()
2. 菜单类

创建一个 TopMenu.py 并在该文件中编写如下代码:
import sys
import tkinter as tk
from tkinter.filedialog import askopenfilenames
import codecs
import time
import hashlib
class TopMenu(tk.Menu):
def __init__(self, predict_function):
super(TopMenu, self).__init__()
# 菜单回调
self.predict_function = predict_function
# 创建菜单
self.file_menu()
self.mail_menu()
self.help_menu()
# 添加文件菜单
def file_menu(self):
file_menu = tk.Menu(master=self, tearoff=False)
file_menu.add_command(label='打开')
file_menu.add_separator()
file_menu.add_command(label='退出', command=sys.exit)
self.add_cascade(label='文件', menu=file_menu)
# 添加邮件菜单
def mail_menu(self):
mail_menu = tk.Menu(master=self, tearoff=False)
mail_menu.add_command(label='识别', command=self.predict_function)
self.add_cascade(label='邮件', menu=mail_menu)
# 添加关于我菜单
def help_menu(self):
about_menu = tk.Menu(master=self, tearoff=False)
about_menu.add_command(label='关于')
self.add_cascade(label='帮助', menu=about_menu)
if __name__ == '__main__':
window = tk.Tk()
window.geometry('800x500+300+300')
menu = TopMenu(predict_function=lambda : print('Hello World'))
window.config(menu=menu)
window.mainloop()
3. 中心文本框

创建 CenterText.py 文件,并在该文件中编写如下代码:
import tkinter as tk
from tkinter.scrolledtext import ScrolledText
import hashlib
from datetime import datetime
class CenText(tk.PanedWindow):
INPUT_NULL = -1
INPUT_SAME = -2
def __init__(self):
super(CenText, self).__init__()
self.config(orient=tk.HORIZONTAL)
self.widgetName = 'CenText'
self.init_widgets()
def init_widgets(self):
# 窗口属性
config = {'bd': 0, 'highlightthickness': 0, 'wrap': tk.NONE}
# 输入文本框
self.mail_area = ScrolledText(**config)
# 信息提示框
self.info_area = tk.Text(**config)
self.set_info_disable()
# 定义字体样式
self.info_area.tag_configure("custom", font=("宋体", 10, "bold"), foreground="red")
self.info_area.tag_configure("normal", font=("宋体", 10, "bold"), foreground="black")
# 添加文本框
self.add(self.mail_area)
self.add(self.info_area)
# 邮件哈希值
self.prev_hexdigest = ''
def set_info_disable(self):
"""使得信息显示框不可输入"""
self.info_area.config(state='disabled')
def set_info_normal(self):
"""使得信息显示框可输入"""
self.info_area.config(state='normal')
def add_info(self, text, font='normal'):
"""信息框添加格式化的信息"""
self.set_info_normal()
# 获得当前时间
cur_time = datetime.now()
cur_time = cur_time.strftime("%Y/%m/%d %H:%M:%S")
self.info_area.insert(tk.END, f'{cur_time} {text}\n', font)
self.set_info_disable()
# 滚动条移动到最后
self.info_area.yview_moveto(1.0)
def get_mail(self):
"""获得邮件输入框内容"""
mail = self.mail_area.get("1.0", tk.END).strip()
if len(mail) == 0:
return CenText.INPUT_NULL
# 计算文本哈希摘要
hash = hashlib.sha256()
hash.update(mail.encode())
curr_hexdigest = hash.hexdigest()
# 判断文本是否变化
if curr_hexdigest == self.prev_hexdigest:
return CenText.INPUT_SAME
self.prev_hexdigest = curr_hexdigest
return mail
if __name__ == '__main__':
window = tk.Tk()
window.geometry('800x500+300+300')
text = CenText()
text.pack(fill=tk.BOTH, expand=True)
button1 = tk.Button(text='添加文本', command=lambda: text.add_info('这是测试文本', font='custom'))
button1.pack(side=tk.BOTTOM)
button2 = tk.Button(text='获得文本', command=lambda: print(text.get_mail()))
button2.pack(side=tk.BOTTOM)
window.mainloop()
4. 状态栏

创建 StatusBar.py 文件,并编写如下代码:
import random
import tkinter as tk
class StatBar(tk.Frame):
def __init__(self):
super(StatBar, self).__init__()
# 设置控件属性
self.config(borderwidth=0, bg='#bdc3c7')
# 初始化子控件
self.init_widgets()
def init_widgets(self):
self.message = tk.Label(self, text=" 准备就绪", bg='#bdc3c7')
self.message.pack(side=tk.LEFT)
def set_message(self, text):
self.message['text'] = text
if __name__ == '__main__':
window = tk.Tk()
window.geometry('800x500+300+300')
sbar = StatBar()
sbar.pack(side=tk.BOTTOM, fill=tk.X)
btn1 = tk.Button(text='改变状态栏文字',
command=lambda: sbar.set_message(f'状态文字修改:{random.randint(0, 100)}'))
btn1.pack(side=tk.TOP)
window.mainloop()
5. 整合控件到主窗口

将头部菜单、中心文本框、底部状态栏创建到主窗口 MainFrame 中,如下:
import tkinter as tk
class MainFrame(tk.Tk):
....
def init_widgets(self):
from TopMenu import TopMenu
from StatBar import StatBar
from CenText import CenText
# 初始化头部菜单
self.menu = TopMenu(predict_function=self.on_menu_predict)
self.config(menu=self.menu)
# 初始化中心文本框
self.text = CenText()
self.text.pack(fill=tk.BOTH, expand=True)
# 初始化底部状态栏
self.sbar = StatBar()
self.sbar.pack(side=tk.BOTTOM, fill=tk.X)
def on_menu_predict(self):
print('预测邮件')
...



冀公网安备13050302001966号