Python+Qt日历事件跨界面数据传递与展示技术求助
事件管理程序跨界面数据传递解决方案
问题背景
我正在开发一款带日历的事件管理程序,支持添加/删除/修改包含名称、地点、时间、日期(日历展示)、组织者、简短描述的事件。程序包含两个界面:
- 主界面:带日历组件,仅展示选中日期的事件名称列表
- 详情界面:用于展示指定事件的完整数据
目前已实现添加事件、切换日历日期、点击事件列表打开详情界面(但无数据填充)的功能,尝试直接传递数据和跨文件SQL查询均失败,需要解决:
- 点击事件列表项后,将对应事件的全量数据传递到详情界面
- 关闭详情界面后可重置状态,支持再次打开其他事件
相关代码
initializer.py(主界面代码)
def calendarDateChanged(self): dateSelected = self.calendarWidget.selectedDate().toPyDate() print("Data selezionata: ", dateSelected) self.updateTaskList(dateSelected) def updateTaskList(self, date): self.tasksListWidget.clear() db = sqlite3.connect("DatabaseCalendario.db") cursor = db.cursor() query = "SELECT name, time FROM tasks WHERE date = ?" row = (date,) results = cursor.execute(query, row).fetchall() for result in results: item = QListWidgetItem(str(result[0])) self.tasksListWidget.addItem(item) def saveChanges(self): db = sqlite3.connect("DatabaseCalendario.db") cursor = db.cursor() date = self.calendarWidget.selectedDate().toPyDate() for i in range(self.tasksListWidget.count()): item = self.tasksListWidget.item(i) task = item.text() if item.checkState() == QtCore.Qt.Checked: query = "UPDATE tasks SET completed = 'YES' WHERE name = ? AND date = ?" else: query = "UPDATE tasks SET completed = 'NO' WHERE name = ? AND date = ?" # 修复原代码变量名错误:name改为task row = (task, date,) cursor.execute(query, row) db.commit() messageBox = QMessageBox() messageBox.setText("Changes saved.") messageBox.setStandardButtons(QMessageBox.Ok) messageBox.exec() def addNewTask(self): db = sqlite3.connect("DatabaseCalendario.db") cursor = db.cursor() newName = str(self.taskLineEdit.text()) date = self.calendarWidget.selectedDate().toPyDate() newLocation = str(self.taskLineEdit1.text()) newTime = str(self.taskLineEdit2.text()) newOrganizer = str(self.taskLineEdit3.text()) newDescription = str(self.taskLineEdit4.text()) query = "INSERT INTO tasks(name, date, location, time, organizer, description) VALUES (?,?,?,?,?,?)" row = (newName, date, newLocation, newTime, newOrganizer, newDescription,) cursor.execute(query, row) db.commit() self.updateTaskList(date) self.taskLineEdit.clear() def openWindow(self): self.window = QtWidgets.QMainWindow() self.ui = Ui_SecondWindow() self.ui.setupUi(self.window) self.window.show() # 以下为尝试过的未成功代码 '''def moveData(self): side = self.tasksListWidget.currentRow() print(side) self.window = QtWidgets.QMainWindow() self.ui = Ui_SecondWindow() self.ui.setupUi(self.window) self.window.show()''' '''def tagImportListClicked(self): print("You clicked the widget") row = self.tasksListWidget.currentRow() self.window = QtWidgets.QMainWindow() self.ui = Ui_SecondWindow() self.ui.setupUi(self.window) self.window.show() self.ui.labelReceiver.setText(row)''' '''def moveData(self): loadUi("mainCalendarioSelezionato.ui", self) self.tasksListWidget.clear() db = sqlite3.connect("DatabaseCalendario.db") cursor = db.cursor()''' if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec())
initializer2.py(详情界面代码)
class Window(QWidget): def __init__(self): super(Window,self).__init__() loadUi("mainCalendarioSelezionato.ui", self) self.modifyButton.clicked.connect(self.updateWidget) def updateWidget(self, date): self.tasksListWidget.clear() db = sqlite3.connect("DatabaseCalendario.db") cursor = db.cursor() query = "SELECT name, time FROM tasks WHERE date = ?" row = (date,) results = cursor.execute(query, row).fetchall() for result in results: item = QListWidgetItem(str(result[0])) self.tasksListWidget.addItem(item) if __name__ == "__main__": app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec())
解决方案
核心思路
通过选中事件的名称+当前日历选中的日期作为唯一查询条件,在打开详情界面时从数据库拉取完整数据;每次打开详情界面都创建新实例,关闭后自动释放,自然实现重置效果。
具体修改步骤
1. 主界面代码修改(initializer.py)
- 绑定列表项点击事件:在主界面的
__init__方法中添加以下代码(确保UI初始化完成后绑定):
self.tasksListWidget.itemClicked.connect(self.onTaskClicked)
- 实现点击事件处理与详情界面打开逻辑,替换原有的
openWindow方法:
def onTaskClicked(self, item): # 获取选中的事件名称 task_name = item.text() # 获取当前日历选中的日期 selected_date = self.calendarWidget.selectedDate().toPyDate() # 打开详情界面并传递关键参数 self.openWindow(task_name, selected_date) def openWindow(self, task_name, selected_date): # 导入详情界面类(确保initializer2.py在Python路径中) from initializer2 import Window # 创建详情界面实例,传递查询参数 self.detail_window = Window(task_name, selected_date) self.detail_window.show()
2. 详情界面代码修改(initializer2.py)
重构详情界面类,支持接收参数并加载完整事件数据:
import sqlite3 from PyQt5.QtWidgets import QWidget from PyQt5.uic import loadUi class Window(QWidget): def __init__(self, task_name, selected_date): super(Window, self).__init__() loadUi("mainCalendarioSelezionato.ui", self) # 存储查询参数 self.task_name = task_name self.selected_date = selected_date # 初始化时加载事件详情 self.loadTaskDetails() # 绑定修改按钮事件(可选,用于实现修改功能) self.modifyButton.clicked.connect(self.updateTask) def loadTaskDetails(self): # 连接数据库查询完整事件数据 db = sqlite3.connect("DatabaseCalendario.db") cursor = db.cursor() # 查询该事件的所有字段 query = "SELECT name, location, time, organizer, description FROM tasks WHERE name = ? AND date = ?" row = (self.task_name, self.selected_date,) result = cursor.execute(query, row).fetchone() if result: # 根据你的UI控件名称修改以下代码,确保与Qt Designer生成的控件名一致 self.name_label.setText(result[0]) self.location_label.setText(result[1]) self.time_label.setText(result[2]) self.organizer_label.setText(result[3]) self.description_label.setText(result[4]) db.close() def updateTask(self): # 实现事件修改逻辑(可选) # 获取界面上修改后的字段值 new_location = self.location_input.text() new_time = self.time_input.text() new_organizer = self.organizer_input.text() new_description = self.description_input.toPlainText() db = sqlite3.connect("DatabaseCalendario.db") cursor = db.cursor() # 更新数据库 query = "UPDATE tasks SET location = ?, time = ?, organizer = ?, description = ? WHERE name = ? AND date = ?" row = (new_location, new_time, new_organizer, new_description, self.task_name, self.selected_date,) cursor.execute(query, row) db.commit() db.close() # 修改完成后关闭界面 self.close() if __name__ == "__main__": from PyQt5.QtWidgets import QApplication import sys app = QApplication(sys.argv) # 测试用例,实际运行时由主界面传递参数 window = Window("测试事件", "2024-05-20") window.show() sys.exit(app.exec())
关键注意事项
- 确保详情界面的UI文件(
mainCalendarioSelezionato.ui)中有对应的展示控件,并且代码中的控件名称与UI文件完全一致(比如name_label、location_label等) - 数据库操作完成后必须关闭连接,避免资源泄漏
- 主界面中用
self.detail_window存储详情界面实例,防止被Python垃圾回收机制提前销毁 - 每次点击事件列表都会创建新的详情界面实例,关闭后实例自动释放,无需额外重置操作
内容的提问来源于stack exchange,提问作者Ender
相关产品推荐
相关产品推荐

