You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python+Qt日历事件跨界面数据传递与展示技术求助

事件管理程序跨界面数据传递解决方案

问题背景

我正在开发一款带日历的事件管理程序,支持添加/删除/修改包含名称、地点、时间、日期(日历展示)、组织者、简短描述的事件。程序包含两个界面:

  • 主界面:带日历组件,仅展示选中日期的事件名称列表
  • 详情界面:用于展示指定事件的完整数据

目前已实现添加事件、切换日历日期、点击事件列表打开详情界面(但无数据填充)的功能,尝试直接传递数据和跨文件SQL查询均失败,需要解决:

  1. 点击事件列表项后,将对应事件的全量数据传递到详情界面
  2. 关闭详情界面后可重置状态,支持再次打开其他事件

相关代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 20:45:46