python: DDD+ORM+pyQt6 using MySql
sql:
create table School #創建表
(
`SchoolId` char(5) NOT NULL comment'主鍵primary key,學校編號',
`SchoolName` nvarchar(500) NOT NULL DEFAULT '' comment' 學校名稱',
`SchoolTelNo` varchar(8) NULL DEFAULT '' comment'電話號碼',
PRIMARY KEY (`SchoolId`) #主鍵
)ENGINE=MyISAM COMMENT='學校表 School Table' DEFAULT CHARSET=utf8; 、
create table Teacher #創建表
(
`TeacherId` char(5) NOT NULL comment'主鍵primary key,學生編號',
`TeacherFirstName` nvarchar(100) NOT NULL DEFAULT '' comment' 名',
`TeacherLastName` nvarchar(20) NOT NULL DEFAULT '' comment' 姓',
`TeacherGender` char(2) NOT NULL DEFAULT '' comment'性別',
`TeacherTelNo` varchar(8) NULL DEFAULT '' comment'電話號碼',
`TeacherSchoolId` char(5) NOT NULL DEFAULT '' comment'外鍵 foreign key 學校ID',
PRIMARY KEY (`TeacherId`), #主鍵
CONSTRAINT TeacherSchool_ibfk_1 FOREIGN KEY(TeacherSchoolId) REFERENCES School(SchoolId) #外鍵
)ENGINE=MyISAM COMMENT='老師表Teacher Table' DEFAULT CHARSET=utf8;
数据处理各层,就用前面的文章提到的就可以了。只是呈现器(MVP)改成pyQt6就可以了。
项目结构:
# 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/29 22:51
# User : geovindu
# Product : PyCharm
# Project : pymysqlDDDQt
# File : school.py
# explain : 学习
import sys
from PyQt6.QtWidgets import QApplication, QTabWidget
from presentation.controllers.school import SchoolController
from presentation.views.school import SchoolView
class SchoolPresenter:
"""
"""
def __init__(self, view, controller: SchoolController):
"""
:param view:
:param controller:
"""
self.view = view
self.controller = controller
self.current_page = 1
self.page_size = 10
self.search_query = ""
self.setup_connections()
self.update_table()
def setup_connections(self):
"""
:return:
"""
self.view.search_button.clicked.connect(self.on_search)
self.view.add_button.clicked.connect(self.on_add)
self.view.edit_button.clicked.connect(self.on_edit)
self.view.delete_button.clicked.connect(self.on_delete)
self.view.prev_button.clicked.connect(self.on_prev_page)
self.view.next_button.clicked.connect(self.on_next_page)
def update_table(self):
"""
:return:
"""
try:
schools = self.controller.get_all_schools(
self.current_page, self.page_size, self.search_query)
print(schools)
self.view.set_table_data(schools)
total_records = self.controller.get_total_schools(self.search_query)
print(total_records)
total_pages = (total_records + self.page_size - 1) // self.page_size
self.view.set_pagination_info(self.current_page, total_pages, total_records)
except Exception as e:
print(f"更新学校表格数据时出错: {e}")
def on_search(self):
"""
:return:
"""
self.search_query = self.view.get_search_query()
self.current_page = 1
self.update_table()
def on_add(self):
"""
:return:
"""
try:
school = self.view.show_add_dialog()
if school:
self.controller.add_school(school)
self.update_table()
self.view.show_message("School added successfully.")
except Exception as e:
print(f"添加学校时出错: {e}")
def on_edit(self):
"""
:return:
"""
try:
row = self.view.get_selected_row()
if row != -1:
school_id = self.view.table.item(row, 0).text()
school = self.controller.get_all_schools(
self.current_page, self.page_size, self.search_query)[row]
edited_school = self.view.show_edit_dialog(school)
if edited_school:
edited_school.SchoolId = school_id
self.controller.update_school(edited_school)
self.update_table()
self.view.show_message("School updated successfully.")
else:
self.view.show_message("Please select a school to edit.")
except Exception as e:
print(f"编辑学校时出错: {e}")
def on_delete(self):
"""
:return:
"""
try:
row = self.view.get_selected_row()
if row != -1:
school_id = self.view.table.item(row, 0).text()
self.controller.delete_school(school_id)
self.update_table()
self.view.show_message("School deleted successfully.")
else:
self.view.show_message("Please select a school to delete.")
except Exception as e:
print(f"删除学校时出错: {e}")
def on_prev_page(self):
"""
:return:
"""
if self.current_page > 1:
self.current_page -= 1
self.update_table()
def on_next_page(self):
"""
:return:
"""
total_schools = self.controller.get_total_schools(self.search_query)
total_pages = (total_schools + self.page_size - 1) // self.page_size
if self.current_page < total_pages:
self.current_page += 1
self.update_table()
# 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/29 22:51
# User : geovindu
# Product : PyCharm
# Project : pymysqlDDDQt
# File : teacher.py
# explain : 学习
from presentation.controllers.teacher import TeacherController
from presentation.views.teacher import TeacherView
from presentation.controllers.school import SchoolController
class TeacherPresenter:
"""
"""
def __init__(self, view, controller:TeacherController,scontroller: SchoolController):
self.view = view
self.controller = controller
self.scontroller = scontroller
self.school_map = None
self.current_page = 1
self.page_size = 10
self.search_query = ""
self.setup_connections()
self.update_table()
def setup_connections(self):
"""
:return:
"""
self.view.search_button.clicked.connect(self.on_search)
self.view.add_button.clicked.connect(self.on_add)
self.view.edit_button.clicked.connect(self.on_edit)
self.view.delete_button.clicked.connect(self.on_delete)
self.view.prev_button.clicked.connect(self.on_prev_page)
self.view.next_button.clicked.connect(self.on_next_page)
# 学校选择
schools = self.scontroller.get_schoolall()
print("schools:")
print(schools)
# 这个有错语
self.school_map = schools # {s.school_name: s.school_id for s in schools}
def update_table(self):
"""
:return:
"""
try:
teachers = self.controller.get_all_teachers(
self.current_page, self.page_size, self.search_query)
self.view.set_table_data(teachers)
total_records = self.controller.get_total_teachers(self.search_query)
total_pages = (total_records + self.page_size - 1) // self.page_size
self.view.set_pagination_info(self.current_page, total_pages, total_records)
except Exception as e:
print(f"更新教师表格数据时出错: {e}")
def on_search(self):
"""
:return:
"""
self.search_query = self.view.get_search_query()
self.current_page = 1
self.update_table()
def on_add(self):
"""
:return:
"""
try:
teacher = self.view.show_add_dialog(self.school_map)
if teacher:
self.controller.add_teacher(teacher)
self.update_table()
self.view.show_message("Teacher added successfully.")
except Exception as e:
print(f"添加教师时出错: {e}")
def on_edit(self):
"""
:return:
"""
try:
row = self.view.get_selected_row()
if row != -1:
teacher_id = self.view.table.item(row, 0).text()
teacher = self.controller.get_all_teachers(
self.current_page, self.page_size, self.search_query)[row]
#
edited_teacher = self.view.show_edit_dialog(teacher,self.school_map)
if edited_teacher:
edited_teacher.TeacherId = teacher_id
self.controller.update_teacher(edited_teacher)
self.update_table()
self.view.show_message("Teacher updated successfully.")
else:
self.view.show_message("Please select a teacher to edit.")
except Exception as e:
print(f"编辑教师时出错: {e}")
def on_delete(self):
"""
:return:
"""
try:
row = self.view.get_selected_row()
if row != -1:
teacher_id = self.view.table.item(row, 0).text()
self.controller.delete_teacher(teacher_id)
self.update_table()
self.view.show_message("Teacher deleted successfully.")
else:
self.view.show_message("Please select a teacher to delete.")
except Exception as e:
print(f"删除教师时出错: {e}")
def on_prev_page(self):
"""
:return:
"""
if self.current_page > 1:
self.current_page -= 1
self.update_table()
def on_next_page(self):
"""
:return:
"""
total_teachers = self.controller.get_total_teachers(self.search_query)
total_pages = (total_teachers + self.page_size - 1) // self.page_size
if self.current_page < total_pages:
self.current_page += 1
self.update_table()
# 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/29 21:34
# User : geovindu
# Product : PyCharm
# Project : pymysqlDDDQt
# File : school.py
# explain : 学习
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QTableWidget, QTableWidgetItem,
QPushButton, QLabel, QLineEdit, QDialog, QFormLayout, QDialogButtonBox, QMessageBox, QMdiArea, QMdiSubWindow
)
from domain.entities.school import School
class SchoolView(QWidget):
"""
"""
def __init__(self):
"""
"""
super().__init__()
self.initUI()
def initUI(self):
"""
:return:
"""
self.mdi_area = QMdiArea()
self.sub_window = QMdiSubWindow()
self.main_widget = QWidget()
self.table = QTableWidget()
self.table.setColumnCount(3)
self.table.setHorizontalHeaderLabels(
['SchoolId', 'SchoolName', 'SchoolTelNo'])
self.search_input = QLineEdit()
self.search_button = QPushButton("Search")
self.add_button = QPushButton("Add")
self.edit_button = QPushButton("Edit")
self.delete_button = QPushButton("Delete")
self.prev_button = QPushButton("Prev")
self.next_button = QPushButton("Next")
self.pagination_label = QLabel()
search_layout = QHBoxLayout()
search_layout.addWidget(self.search_input)
search_layout.addWidget(self.search_button)
button_layout = QHBoxLayout()
button_layout.addWidget(self.add_button)
button_layout.addWidget(self.edit_button)
button_layout.addWidget(self.delete_button)
button_layout.addWidget(self.prev_button)
button_layout.addWidget(self.next_button)
button_layout.addWidget(self.pagination_label)
layout = QVBoxLayout()
layout.addLayout(search_layout)
layout.addWidget(self.table)
layout.addLayout(button_layout)
self.main_widget.setLayout(layout)
self.sub_window.setWidget(self.main_widget)
self.mdi_area.addSubWindow(self.sub_window)
main_layout = QVBoxLayout()
main_layout.addWidget(self.mdi_area)
self.setLayout(main_layout)
def set_table_data(self, schools):
"""
:param schools:
:return:
"""
self.table.setRowCount(len(schools))
for row, school in enumerate(schools):
self.table.setItem(row, 0, QTableWidgetItem(school.school_id))
self.table.setItem(row, 1, QTableWidgetItem(school.school_name))
self.table.setItem(row, 2, QTableWidgetItem(school.school_tel_no))
def get_selected_row(self):
"""
:return:
"""
selected_items = self.table.selectedItems()
if selected_items:
return selected_items[0].row()
return -1
def get_search_query(self):
"""
:return:
"""
return self.search_input.text()
def show_add_dialog(self):
"""
:return:
"""
dialog = QDialog(self)
dialog.setWindowTitle("Add School")
layout = QFormLayout()
id_input = QLineEdit()
name_input = QLineEdit()
tel_input = QLineEdit()
layout.addRow("School ID:", id_input)
layout.addRow("School Name:", name_input)
layout.addRow("School Tel No:", tel_input)
button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
button_box.accepted.connect(dialog.accept)
button_box.rejected.connect(dialog.reject)
layout.addWidget(button_box)
dialog.setLayout(layout)
if dialog.exec() == QDialog.DialogCode.Accepted:
school_id = id_input.text()
name = name_input.text()
tel_no = tel_input.text()
return School(SchoolId=school_id, SchoolName=name, SchoolTelNo=tel_no)
return None
def show_edit_dialog(self, school):
"""
:param school:
:return:
"""
dialog = QDialog(self)
dialog.setWindowTitle("Edit School")
layout = QFormLayout()
id_input = QLineEdit(school.school_id)
name_input = QLineEdit(school.school_name)
tel_input = QLineEdit(school.school_tel_no)
layout.addRow("School ID:", id_input)
layout.addRow("School Name:", name_input)
layout.addRow("School Tel No:", tel_input)
button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
button_box.accepted.connect(dialog.accept)
button_box.rejected.connect(dialog.reject)
layout.addWidget(button_box)
dialog.setLayout(layout)
if dialog.exec() == QDialog.DialogCode.Accepted:
school.SchoolId = id_input.text()
school.SchoolName = name_input.text()
school.SchoolTelNo = tel_input.text()
return school
return None
def show_message(self, message):
"""
:param message:
:return:
"""
QMessageBox.information(self, 'Message', message)
def set_pagination_info(self, current_page, total_pages, total_records):
"""
:param current_page:
:param total_pages:
:param total_records:
:return:
"""
info_text = f"当前页: {current_page} / 总页数: {total_pages} 总记录数: {total_records}"
self.pagination_label.setText(info_text)
# 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/29 21:34
# User : geovindu
# Product : PyCharm
# Project : pymysqlDDDQt
# File : teacher.py
# explain : 学习
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QHBoxLayout, QTableWidget, QTableWidgetItem,
QPushButton, QLabel, QLineEdit, QDialog, QFormLayout, QDialogButtonBox, QMessageBox, QMdiArea, QMdiSubWindow, QComboBox
)
from domain.entities.teacher import Teacher
class TeacherView(QWidget):
"""
"""
def __init__(self):
"""
"""
super().__init__()
self.initUI()
def initUI(self):
"""
:return:
"""
self.mdi_area = QMdiArea()
self.sub_window = QMdiSubWindow()
self.main_widget = QWidget()
self.table = QTableWidget()
self.table.setColumnCount(6)
self.table.setHorizontalHeaderLabels([
'TeacherId', 'TeacherFirstName', 'TeacherLastName',
'TeacherGender', 'TeacherTelNo', 'TeacherSchoolId'
])
self.search_input = QLineEdit()
self.search_button = QPushButton("Search")
self.add_button = QPushButton("Add")
self.edit_button = QPushButton("Edit")
self.delete_button = QPushButton("Delete")
self.prev_button = QPushButton("Prev")
self.next_button = QPushButton("Next")
self.pagination_label = QLabel()
search_layout = QHBoxLayout()
search_layout.addWidget(self.search_input)
search_layout.addWidget(self.search_button)
button_layout = QHBoxLayout()
button_layout.addWidget(self.add_button)
button_layout.addWidget(self.edit_button)
button_layout.addWidget(self.delete_button)
button_layout.addWidget(self.prev_button)
button_layout.addWidget(self.next_button)
button_layout.addWidget(self.pagination_label)
layout = QVBoxLayout()
layout.addLayout(search_layout)
layout.addWidget(self.table)
layout.addLayout(button_layout)
self.main_widget.setLayout(layout)
self.sub_window.setWidget(self.main_widget)
self.mdi_area.addSubWindow(self.sub_window)
main_layout = QVBoxLayout()
main_layout.addWidget(self.mdi_area)
self.setLayout(main_layout)
def set_table_data(self, teachers):
"""
:param teachers:
:return:
"""
self.table.setRowCount(len(teachers))
for row, teacher in enumerate(teachers):
self.table.setItem(row, 0, QTableWidgetItem(teacher.teacher_id))
self.table.setItem(row, 1, QTableWidgetItem(
teacher.first_name))
self.table.setItem(row, 2, QTableWidgetItem(
teacher.last_name))
self.table.setItem(row, 3, QTableWidgetItem(teacher.gender))
self.table.setItem(row, 4, QTableWidgetItem(teacher.tel_no))
self.table.setItem(row, 5, QTableWidgetItem(
teacher.school_id))
def get_selected_row(self):
"""
:return:
"""
selected_items = self.table.selectedItems()
if selected_items:
return selected_items[0].row()
return -1
def get_search_query(self):
"""
:return:
"""
return self.search_input.text()
def show_add_dialog(self,school_map):
"""
:param school_map:
:return:
"""
dialog = QDialog(self)
dialog.setWindowTitle("Add Teacher")
layout = QFormLayout()
id_input = QLineEdit()
first_name_input = QLineEdit()
last_name_input = QLineEdit()
gender_input = QLineEdit()
tel_input = QLineEdit()
school_combo = QComboBox()
# 获取所有学校信息
schools =school_map # self.school_service.get_schoolall()
print("获取所有学校信息")
print(schools)
for school in school_map:
school_combo.addItem(f"{school.school_id} - {school.school_name}", school.school_id)
layout.addRow("Teacher ID:", id_input)
layout.addRow("First Name:", first_name_input)
layout.addRow("Last Name:", last_name_input)
layout.addRow("Gender:", gender_input)
layout.addRow("Tel No:", tel_input)
layout.addRow("School:", school_combo)
button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
button_box.accepted.connect(dialog.accept)
button_box.rejected.connect(dialog.reject)
layout.addWidget(button_box)
dialog.setLayout(layout)
if dialog.exec() == QDialog.DialogCode.Accepted:
teacher_id = id_input.text()
first_name = first_name_input.text()
last_name = last_name_input.text()
gender = gender_input.text()
tel_no = tel_input.text()
school_id = school_combo.currentData()
return Teacher(TeacherId=teacher_id, TeacherFirstName=first_name,
TeacherLastName=last_name, TeacherGender=gender,
TeacherTelNo=tel_no, TeacherSchoolId=school_id)
return None
def show_edit_dialog(self, teacher,school_map):
"""
:param teacher:
:param school_map:
:return:
"""
dialog = QDialog(self)
dialog.setWindowTitle("Edit Teacher")
layout = QFormLayout()
id_input = QLineEdit(teacher.teacher_id)
first_name_input = QLineEdit(teacher.first_name)
last_name_input = QLineEdit(teacher.last_name)
gender_input = QLineEdit(teacher.gender)
tel_input = QLineEdit(teacher.tel_no)
school_combo = QComboBox()
# 获取所有学校信息
schools = school_map # self.school_service.get_schoolall()
for school in schools:
school_combo.addItem(f"{school.school_id} - {school.school_name}", school.school_id)
if school.school_id == teacher.school_id:
school_combo.setCurrentIndex(school_combo.count() - 1)
layout.addRow("Teacher ID:", id_input)
layout.addRow("First Name:", first_name_input)
layout.addRow("Last Name:", last_name_input)
layout.addRow("Gender:", gender_input)
layout.addRow("Tel No:", tel_input)
layout.addRow("School:", school_combo)
button_box = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel)
button_box.accepted.connect(dialog.accept)
button_box.rejected.connect(dialog.reject)
layout.addWidget(button_box)
dialog.setLayout(layout)
if dialog.exec() == QDialog.DialogCode.Accepted:
teacher.TeacherId = id_input.text()
teacher.TeacherFirstName = first_name_input.text()
teacher.TeacherLastName = last_name_input.text()
teacher.TeacherGender = gender_input.text()
teacher.TeacherTelNo = tel_input.text()
teacher.TeacherSchoolId = school_combo.currentData()
return teacher
return None
def show_message(self, message):
"""
:param message:
:return:
"""
QMessageBox.information(self, 'Message', message)
def set_pagination_info(self, current_page, total_pages, total_records):
"""
:param current_page:
:param total_pages:
:param total_records:
:return:
"""
info_text = f"当前页: {current_page} / 总页数: {total_pages} 总记录数: {total_records}"
self.pagination_label.setText(info_text)
输出:
加上登录进入主窗口
# 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/30 13:12
# User : geovindu
# Product : PyCharm
# Project : pymysqlDDDQt
# File : login.py
# explain : 学习
import sys
from PyQt6.QtWidgets import QApplication, QTabWidget, QWidget, QVBoxLayout, QLabel, QLineEdit, QPushButton, QMessageBox,QMenuBar, QMenu, QMainWindow,QStackedWidget
from PyQt6.QtGui import QIcon
from PyQt6.QtGui import QAction
from PyQt6.QtSql import QSqlDatabase, QSqlQuery
'''
# 1 ok
class MainWindow(QWidget):
"""
# 假设其他导入和控制器/视图类已正确实现
"""
def __init__(self):
super().__init__()
self.presenters = {} # 使用字典持久保存Presenter
self.initUI()
def initUI(self):
self.tab_widget = QTabWidget(self)
# 学校视图
self.school_view = SchoolView()
school_controller = SchoolController()
SchoolPresenter(self.school_view, school_controller)
self.presenters['school'] = SchoolPresenter # 保持强引用
self.tab_widget.addTab(self.school_view, "学校管理")
# 教师视图
self.teacher_view = TeacherView()
teacher_controller = TeacherController()
TeacherPresenter(self.teacher_view, teacher_controller, school_controller)
self.presenters['teacher'] = TeacherPresenter # 保持强引用
self.tab_widget.addTab(self.teacher_view, "教师管理")
# 用户视图
self.user_view = UserView()
user_controller = UserController()
UserPresenter(self.user_view, user_controller)
self.presenters['user'] = UserPresenter # 保持强引用
self.tab_widget.addTab(self.user_view, "用户管理")
layout = QVBoxLayout(self)
layout.addWidget(self.tab_widget)
self.setLayout(layout)
self.setWindowTitle("主管理界面")
self.resize(800, 600)
class LoginWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
layout = QVBoxLayout()
self.username_label = QLabel("用户名:")
self.username_input = QLineEdit()
self.password_label = QLabel("密码:")
self.password_input = QLineEdit()
self.password_input.setEchoMode(QLineEdit.EchoMode.Password)
self.login_button = QPushButton("登录")
self.login_button.clicked.connect(self.login)
layout.addWidget(self.username_label)
layout.addWidget(self.username_input)
layout.addWidget(self.password_label)
layout.addWidget(self.password_input)
layout.addWidget(self.login_button)
self.setLayout(layout)
self.setWindowTitle("登录")
self.setFixedSize(300, 200)
def login(self):
username = self.username_input.text()
password = self.password_input.text()
ubll = UserController()
user = ubll.get_user_by_username(username)
if user and user.password == password:
self.main_window = MainWindow() # 创建主窗口实例
self.main_window.show() # 显示主窗口
self.close() # 关闭登录窗口
else:
QMessageBox.warning(self, "登录失败", "用户名或密码错误")
if __name__ == '__main__':
try:
app = QApplication(sys.argv)
app.setWindowIcon(QIcon('./favicon.ico'))
login_window = LoginWindow()
login_window.show()
sys.exit(app.exec())
except Exception as e:
QMessageBox.critical(None, "启动错误", f"应用程序启动失败: {str(e)}")
sys.exit(1)
'''
''' 2 ok tab 考虑事件无效问题
class LoginWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
# self.db = self.connect_to_database()
self.tab_widget = None
def initUI(self):
layout = QVBoxLayout()
self.username_label = QLabel("用户名:")
self.username_input = QLineEdit()
self.password_label = QLabel("密码:")
self.password_input = QLineEdit()
self.password_input.setEchoMode(QLineEdit.EchoMode.Password)
self.login_button = QPushButton("登录")
self.login_button.clicked.connect(self.login)
layout.addWidget(self.username_label)
layout.addWidget(self.username_input)
layout.addWidget(self.password_label)
layout.addWidget(self.password_input)
layout.addWidget(self.login_button)
self.setLayout(layout)
self.setWindowTitle("登录")
def login(self):
username = self.username_input.text()
password = self.password_input.text()
print('login')
ubll = UserController()
user = ubll.get_user_by_username(username)
print("user:", user)
if user is None or user.password != password:
QMessageBox.warning(self, "登录失败", "用户名或密码错误,请重试。")
else:
QMessageBox.information(self, "登录成功", "欢迎登录!")
self.show_main_window()
self.close()
def show_main_window(self):
try:
# 不设置父窗口
self.tab_widget = QTabWidget()
school_view = SchoolView()
school_controller = SchoolController()
school_presenter = SchoolPresenter(school_view, school_controller)
self.tab_widget.addTab(school_view, "Schools")
teacher_view = TeacherView()
teacher_controller = TeacherController()
teacher_presenter = TeacherPresenter(teacher_view, teacher_controller, school_controller)
self.tab_widget.addTab(teacher_view, "Teachers")
user_view = UserView()
user_controller = UserController()
user_presenter = UserPresenter(user_view, user_controller)
#self.presenters['uers'] = user_presenter # 保持强引用
self.tab_widget.addTab(user_view, "Users")
self.tab_widget.show()
except Exception as e:
QMessageBox.critical(self, "主窗体显示错误", f"显示主窗体时出现错误: {str(e)}")
if __name__ == '__main__':
try:
app = QApplication(sys.argv)
app.setWindowIcon(QIcon('./favicon.ico'))
login_window = LoginWindow()
login_window.show()
sys.exit(app.exec())
except Exception as e:
print(f"启动应用程序时出错: {e}")
'''
# 3 菜单式的 ok
class LoginWindow(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.school_view = None
self.teacher_view = None
self.user_view = None
self.school_presenter = None
self.teacher_presenter = None
self.user_presenter = None
self.main_window = None # 新增类属性
def initUI(self):
layout = QVBoxLayout()
self.username_label = QLabel("用户名:")
self.username_input = QLineEdit()
self.password_label = QLabel("密码:")
self.password_input = QLineEdit()
self.password_input.setEchoMode(QLineEdit.EchoMode.Password)
self.login_button = QPushButton("登录")
self.login_button.clicked.connect(self.login)
layout.addWidget(self.username_label)
layout.addWidget(self.username_input)
layout.addWidget(self.password_label)
layout.addWidget(self.password_input)
layout.addWidget(self.login_button)
self.setLayout(layout)
self.setWindowTitle("登录")
def login(self):
username = self.username_input.text()
password = self.password_input.text()
from presentation.controllers.user import UserController
ubll = UserController()
user = ubll.get_user_by_username(username)
print("user:", user)
if user is None or user.password != password:
QMessageBox.warning(self, "登录失败", "用户名或密码错误,请重试。")
else:
QMessageBox.information(self, "登录成功", "欢迎登录!")
self.show_main_window()
self.close()
def show_main_window(self):
try:
# 正确创建主窗口并保持引用
self.main_window = QMainWindow() # 不再需要 QApplication.instance()
self.main_window.setWindowTitle("Main Window")
# 创建菜单栏 (关键修改1:直接使用 main_window 的方法创建)
menu_bar = self.main_window.menuBar() # 这是正确获取 QMainWindow 菜单栏的方法
# 创建菜单项
main_menu = menu_bar.addMenu("Main")
# 创建动作并绑定 (关键修改2:指定父级为菜单栏)
schools_action = QAction("Schools", menu_bar)
schools_action.triggered.connect(self.show_schools_view)
main_menu.addAction(schools_action)
teachers_action = QAction("Teachers", menu_bar)
teachers_action.triggered.connect(self.show_teachers_view)
main_menu.addAction(teachers_action)
users_action = QAction("Users", menu_bar)
users_action.triggered.connect(self.show_users_view)
main_menu.addAction(users_action)
# 初始化视图和 Presenter
self.init_views()
# 设置中央部件 (关键修改3:使用 StackedWidget 管理视图切换)
self.stacked_widget = QStackedWidget()
self.stacked_widget.addWidget(self.school_view)
self.stacked_widget.addWidget(self.teacher_view)
self.stacked_widget.addWidget(self.user_view)
self.main_window.setCentralWidget(self.stacked_widget)
# 设置窗口属性
self.main_window.setMinimumSize(800, 600)
self.main_window.show()
except Exception as e:
import traceback
traceback.print_exc()
QMessageBox.critical(self, "Error", f"Failed to show main window: {str(e)}")
def init_views(self):
"""
初始化所有视图和 Presenter
"""
from presentation.controllers.school import SchoolController
from presentation.views.school import SchoolView
from presentation.controllers.teacher import TeacherController
from presentation.views.teacher import TeacherView
from presentation.Presenter.school import SchoolPresenter
from presentation.Presenter.teacher import TeacherPresenter
from presentation.views.user import UserView
from presentation.controllers.user import UserController
from presentation.Presenter.user import UserPresenter
# 学校视图
self.school_view = SchoolView()
school_controller = SchoolController()
self.school_presenter = SchoolPresenter(self.school_view, school_controller)
# 教师视图
self.teacher_view = TeacherView()
teacher_controller = TeacherController()
self.teacher_presenter = TeacherPresenter(self.teacher_view, teacher_controller, school_controller)
# 用户视图
self.user_view = UserView()
user_controller = UserController()
self.user_presenter = UserPresenter(self.user_view, user_controller)
def show_schools_view(self):
self.school_view.show()
self.teacher_view.hide()
self.user_view.hide()
def show_teachers_view(self):
self.school_view.hide()
self.teacher_view.show()
self.user_view.hide()
def show_users_view(self):
self.school_view.hide()
self.teacher_view.hide()
self.user_view.show()
# encoding: utf-8
# 版权所有 2025 ©涂聚文有限公司 ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述: python.exe -m pip install --upgrade pip
# pip install sqlalchemy ORM DDD MVC pip install pymysql
# Author : geovindu,Geovin Du 涂聚文.
# IDE : PyCharm 2023.1 python 3.11
# OS : windows 10 https://doc.qt.io/qtforpython-6/PySide6/QtGui/QAction.html
# python.exe -m pip install --upgrade pip
# pip install pymysql pip install SQLAlchemy
# pip3 install pyqt6
# pip install pyside6
# pip install pyqt6-tools
# database : mysql 9.0 sql server 2019, postgreSQL 17.0 oracle 21c Neo4j
# Datetime : 2025/3/20 20:32
# User : geovindu
# Product : PyCharm
# Project : pyMySqlDDDOrmDemo
# File : main.py
# explain : 学习
import sys
from PyQt6.QtWidgets import QApplication, QTabWidget, QWidget, QVBoxLayout, QLabel, QLineEdit, QPushButton, QMessageBox,QMenuBar, QMenu, QMainWindow,QStackedWidget
from PyQt6.QtGui import QIcon
from PyQt6.QtGui import QAction
from PyQt6.QtSql import QSqlDatabase, QSqlQuery
from presentation.views.login import LoginWindow
if __name__ == '__main__':
"""
"""
app = QApplication(sys.argv)
app.setWindowIcon(QIcon('./favicon.ico'))
login_window = LoginWindow()
login_window.show()
sys.exit(app.exec())
"""
from presentation.controllers.school import SchoolController
from presentation.views.school import SchoolView
from presentation.controllers.teacher import TeacherController
from presentation.views.teacher import TeacherView
from presentation.Presenter.school import SchoolPresenter
from presentation.Presenter.teacher import TeacherPresenter
from presentation.views.user import UserView
from presentation.controllers.user import UserController
from presentation.Presenter.user import UserPresenter
# 写在文件头
from presentation.controllers import *
from presentation.Presenter import *
from presentation.views import *
"""
from presentation.controllers import SchoolController,TeacherController,UserController
from presentation.Presenter import SchoolPresenter,TeacherPresenter,UserPresenter
from presentation.views import SchoolView,TeacherView,UserView