python: login form
# encoding: utf-8
# 版权所有 2025 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author : geovindu,Geovin Du 涂聚文.
# IDE : PyCharm 2023.1 python 3.11
# OS : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 oracle 21c Neo4j
# Datetime : 2025/3/18 20:02
# User : geovindu
# Product : PyCharm
# Project : pyMySqlDDDOrmDemo
# File : user.py
# explain : 学习
import tkinter as tk
from tkinter import messagebox
from tkinter import ttk
from tkinter import messagebox
from domain.entities.user import User
class LoginView(tk.Tk):
"""
登录用户
"""
def __init__(self):
super().__init__()
self.title("IT管理系统")
window_width1 = 400
window_height1 = 300
self.iconbitmap("favicon.ico")
self.resizable(False, False)
self.maxsize(2000, 1000)
self.minsize(window_width1, window_height1)
x = (2000 - window_width1) // 2
y = (1000 - window_height1) // 2
self.geometry(f'{window_width1}x{window_height1}+{x}+{y}')
tk.Label(self, text="用户名").grid(row=0, column=0, padx=5, pady=5)
self.username_entry = tk.Entry(self)
self.username_entry.grid(row=0, column=1, padx=5, pady=5)
tk.Label(self, text="密码").grid(row=1, column=0, padx=5, pady=5)
self.password_entry = tk.Entry(self, show="*")
self.password_entry.grid(row=1, column=1, padx=5, pady=5)
self.login_button = tk.Button(self, text=' 登入 ', command=self.on_login_click)
self.login_button.grid(row=2, column=1, padx=5, pady=5)
def on_login_click(self):
username = self.username_entry.get()
password = self.password_entry.get()
self.notify_login_attempt(username, password)
def set_login_result(self, success, message):
if success:
messagebox.showinfo("Success!", message)
self.destroy()
else:
messagebox.showerror("Error!", message)
def notify_login_attempt(self, username, password):
pass
# 视图层
class UserView(object):
"""
用户管理
"""
def __init__(self, parent):
"""
:param parent:
"""
self.frame = tk.Frame(parent)
# 搜索框
self.search_frame = ttk.Frame(self.frame)
self.search_frame.pack(pady=10)
self.search_var = tk.StringVar()
self.search_entry = ttk.Entry(self.search_frame, textvariable=self.search_var)
self.search_entry.pack(side=tk.LEFT,pady=10)
self.search_button = ttk.Button(self.search_frame, text="搜索")
self.search_button.pack(side=tk.LEFT,pady=5)
# Treeview
self.tree = ttk.Treeview(self.frame, columns=('Id', 'UserName', 'Password', 'email'), show='headings')
self.tree.heading('Id', text='ID')
self.tree.heading('UserName', text='用户名')
self.tree.heading('Password', text='密码')
self.tree.heading('email', text='邮箱')
self.tree.pack(pady=20)
self.tree.bind("<Double-1>", self.on_double_click)
# 分页按钮
self.pagination_frame = ttk.Frame(self.frame)
self.pagination_frame.pack(pady=10)
self.button_frame = ttk.Frame(self.pagination_frame)
self.button_frame.pack(pady=10)
self.prev_button = ttk.Button(self.pagination_frame, text="上一页")
self.prev_button.pack(side=tk.LEFT, padx=10)
self.page_label = ttk.Label(self.pagination_frame, text="Page 1 of 1")
self.page_label.pack(side=tk.LEFT, padx=5)
self.next_button = ttk.Button(self.pagination_frame, text="下一页")
self.next_button.pack(side=tk.LEFT, padx=10)
self.button_frame = ttk.Frame(self.frame)
self.button_frame.pack(pady=10)
# 添加按钮
self.add_button = ttk.Button(self.button_frame, text="添加")
self.add_button.pack(side=tk.RIGHT, padx=10)
self.edit_button = ttk.Button(self.button_frame, text="编辑")
self.edit_button.pack(side=tk.LEFT, padx=5)
# 删除按钮
self.delete_button = ttk.Button(self.button_frame, text="删除")
self.delete_button.pack(side=tk.RIGHT, padx=10)
self.presenter = None
def clear_tree(self):
"""
:return:
"""
for item in self.tree.get_children():
self.tree.delete(item)
def populate_tree(self, users):
"""
:param users:
:return:
"""
for user in users:
print(user)
print(user.username)
self.tree.insert('', 'end', values=(user.id,user.username, user.email,user.password))
def update_page_label(self, current_page, total_pages,total,pagesize):
"""
:param current_page:
:param total_pages:
:param total:
:param pagesize
:return:
"""
self.page_label.config(text=f"第 {current_page} 页/ 共 {total_pages} 页 每页{pagesize}条/共{total} 条记录")
def show_add_window(self,schoolmap, save_callback):
top = tk.Toplevel(self.frame)
top.title("添加用户")
# top.iconbitmap("favicon.ico")
# 用户名
ttk.Label(top, text="用户名:").grid(row=0, column=0, padx=10, pady=5)
username_entry = ttk.Entry(top)
username_entry.grid(row=0, column=1, padx=10, pady=5)
# 密码
ttk.Label(top, text="密码:").grid(row=1, column=0, padx=10, pady=5)
password_entry = ttk.Entry(top)
password_entry.grid(row=1, column=1, padx=10, pady=5)
# 邮箱
ttk.Label(top, text="邮箱:").grid(row=2, column=0, padx=10, pady=5)
email_entry = ttk.Entry(top)
email_entry.grid(row=2, column=1, padx=10, pady=5)
def save_user():
username = username_entry.get()
password = password_entry.get()
email = email_entry.get()
if username and password and email:
if all([username, password, email]):
save_callback(username, password, email)
top.destroy()
else:
messagebox.showerror("错误", "用户名、密码和邮箱不能为空")
# 保存按钮
ttk.Button(top, text="保存", command=save_user).grid(row=3, column=0, columnspan=2, pady=10)
def open_edit_window(self, user_map, user_id, username, password, email, update_callback):
if user_id:
top = tk.Toplevel(self.frame)
top.title("编辑用户")
# top.iconbitmap("favicon.ico")
# 用户名
ttk.Label(top, text="用户名:").grid(row=0, column=0, padx=10, pady=5)
top.username_entry = ttk.Entry(top)
top.username_entry.insert(0, username)
top.username_entry.grid(row=0, column=1, padx=10, pady=5)
# 密码
ttk.Label(top, text="密码:").grid(row=1, column=0, padx=10, pady=5)
top.password_entry = ttk.Entry(top)
top.password_entry.insert(0, password)
top.password_entry.grid(row=1, column=1, padx=10, pady=5)
# 邮箱
ttk.Label(top, text="邮箱:").grid(row=2, column=0, padx=10, pady=5)
top.email_entry = ttk.Entry(top)
top.email_entry.insert(0, email)
top.email_entry.grid(row=2, column=1, padx=10, pady=5)
def update_user():
username = top.username_entry.get()
password = top.password_entry.get()
email = top.email_entry.get()
if username and password and email:
update_callback(user_id, username, password, email)
top.destroy()
else:
messagebox.showerror("错误", "用户名、密码和邮箱不能为空")
# 保存按钮
ttk.Button(top, text="保存", command=update_user).grid(row=3, column=0, columnspan=2, pady=10)
def on_double_click(self, event):
selected_item = self.tree.selection()
if selected_item:
values = self.tree.item(selected_item, 'values')
user_id, username, password, email = values
# 检查 presenter 是否已经正确初始化
if self.presenter:
self.presenter.edit(user_id, username, password, email)
else:
print("Presenter 未初始化")
# encoding: utf-8
# 版权所有 2025 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:
# Author : geovindu,Geovin Du 涂聚文.
# IDE : PyCharm 2023.1 python 3.11
# OS : windows 10
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 oracle 21c Neo4j
# Datetime : 2025/3/18 20:02
# User : geovindu
# Product : PyCharm
# Project : pyMySqlDDDOrmDemo
# File : user.py
# explain : 学习
from presentation.views.user import LoginView
from application.services.user import UserService
from domain.entities.user import User
import tkinter as tk
from infrastructure.repositories import SchoolRepository,TeacherRepository # init 必须配置,才可以这样引用
# from infrastructure.repositories import *
from application.services import SchoolService, TeacherService
# from application.services import *
from presentation.views import SchoolView, TeacherView
# from presentation.views import *
from presentation.controllers import SchoolController, TeacherController
# from presentation.controllers import *
from infrastructure.repositories.user import UserRepository
from presentation.views.user import UserView
from application.services.user import UserService
class UserController:
"""
登录窗口
"""
def __init__(self, view: LoginView, user_repository: UserService):
"""
:param view:
:param user_repository:
"""
self.view = view
self.user_repository = user_repository
self.view.notify_login_attempt = self.handle_login_attempt
def handle_login_attempt(self, username, password):
"""
:param username:
:param password:
:return:
"""
if not username or not password:
self.view.set_login_result(False, "账号密码不可为空")
return
user = self.user_repository.get_user_by_username(username)
if user is None or user.password != password:
self.view.set_login_result(False, "账号密码错误")
else:
self.view.set_login_result(True, "欢迎登入管理系统")
root = tk.Tk()
root.title("学校老师管理系统")
# 创建数据库存储库实例
school_repository = SchoolRepository()
teacher_repository = TeacherRepository()
# 创建服务实例
school_service = SchoolService(school_repository)
teacher_service = TeacherService(teacher_repository)
# 创建视图实例
school_view = SchoolView(root)
teacher_view = TeacherView(root)
school_view.frame.pack_forget()
teacher_view.frame.pack_forget()
user_repository = UserRepository()
userserver=UserService(user_repository)
userview = UserView(root)
userview.frame.pack_forget()
#presenter = UserPresenter(userserver,userview)
# 创建控制器实例
school_controller = SchoolController(school_service, school_view)
# 需要加上学校的务服实例。便于选择学校
teacher_controller = TeacherController(teacher_service, school_service, teacher_view)
user_controller = UserPresenter(userserver, userview)
# 创建主菜单
menubar = tk.Menu(root)
root.config(menu=menubar)
# 创建主菜单下的子菜单
main_menu = tk.Menu(menubar, tearoff=0)
menubar.add_cascade(label="管理菜单", menu=main_menu)
# 学校管理子菜单
school_menu = tk.Menu(main_menu, tearoff=0)
main_menu.add_cascade(label="学校管理", menu=school_menu)
school_menu.add_command(label="查看学校信息", command=lambda: (
school_view.frame.pack(),
teacher_view.frame.pack_forget(), # 隐藏
userview.frame.pack_forget()
))
# 老师管理子菜单
teacher_menu = tk.Menu(main_menu, tearoff=0)
main_menu.add_cascade(label="老师管理", menu=teacher_menu)
teacher_menu.add_command(label="查看老师信息", command=lambda: (
teacher_view.frame.pack(),
school_view.frame.pack_forget(), # 隐藏
userview.frame.pack_forget()
))
# 用户管理
teacher_menu = tk.Menu(main_menu, tearoff=0)
main_menu.add_cascade(label="用户管理", menu=teacher_menu)
teacher_menu.add_command(label="查看用户信息", command=lambda: (
teacher_view.frame.pack_forget(),
school_view.frame.pack_forget(), # 隐藏
userview.frame.pack()
))
root.iconbitmap("favicon.ico")
root.mainloop()
# 呈现器层
class UserPresenter:
"""
用户管理
"""
def __init__(self, service: UserService, view):
self.service = service
self.view = view
self.current_page = 1
self.page_size = 10
self.search_query = ""
self.total_pages = 1
self.total_count = 0
self.user_map = None
self.view.search_button.config(command=self.search)
self.view.add_button.config(command=self.add)
#self.view.edit_button.config(command=self.edit)
self.view.edit_button.config(command=lambda: self.edit(None, None, None, None))
self.view.delete_button.config(command=self.delete)
self.view.prev_button.config(command=self.prev_page)
self.view.next_button.config(command=self.next_page)
#self.view.tree.on_double_click(command=self.editclick)
self.view.presenter = self
self.load_data()
def load_data(self):
"""
:return:
"""
users = self.service.get_all_users(self.current_page, self.page_size, self.search_query)
print(users)
self.total_count = self.service.get_total_pages(self.search_query)
self.total_pages = (self.total_count + self.page_size - 1) // self.page_size
self.view.clear_tree()
self.view.populate_tree(users)
print(self.current_page,self.total_count, self.total_pages)
self.view.update_page_label(self.current_page, self.total_pages, self.total_count, self.page_size)
self.view.prev_button.config(state=tk.NORMAL if self.current_page > 1 else tk.DISABLED)
self.view.next_button.config(state=tk.NORMAL if self.current_page < self.total_pages else tk.DISABLED)
# 选择
usersd = self.service.get_all()
# 这个有错语
self.user_map = {s.username: s.id for s in usersd}
def search(self):
"""
:return:
"""
self.search_query = self.view.search_entry.get()
self.current_page = 1
self.load_data()
def prev_page(self):
"""
:return:
"""
if self.current_page > 1:
self.current_page -= 1
self.load_data()
def next_page(self):
"""
:return:
"""
if self.current_page < self.total_pages:
self.current_page += 1
self.load_data()
def add(self):
"""
:return:
"""
def save_callback(username, password, email):
"""
:param teacher_id:
:param first_name:
:param last_name:
:param gender:
:param tel_no:
:param school_id:
:return:
"""
new_user = User(username, password, email)
self.service.add_user(username, password, email)
self.load_data()
# 打开添加窗口
self.view.show_add_window(self.user_map, save_callback)
def edit(self, user_id, username, password, email):
if not user_id:
selected_item = self.view.tree.selection()
if selected_item:
values = self.view.tree.item(selected_item, 'values')
user_id, username, password, email = values
if user_id:
def update_callback(user_id, username, password, email):
updated_user = User(user_id, username, password, email)
self.service.update_user(user_id, username, password, email)
self.load_data()
self.view.open_edit_window(self.user_map, user_id, username, password, email, update_callback)
def delete(self):
"""
:return:
"""
selected_item = self.view.tree.selection()
if selected_item:
user_id = self.view.tree.item(selected_item, 'values')[0]
self.service.delete_user(user_id)
self.load_data()
哲学管理(学)人生, 文学艺术生活, 自动(计算机学)物理(学)工作, 生物(学)化学逆境, 历史(学)测绘(学)时间, 经济(学)数学金钱(理财), 心理(学)医学情绪, 诗词美容情感, 美学建筑(学)家园, 解构建构(分析)整合学习, 智商情商(IQ、EQ)运筹(学)生存.---Geovin Du(涂聚文)
浙公网安备 33010602011771号