PyQt5技术问询:跨类实现登录窗口向主窗口传递用户名
解决Qt登录窗口向主窗口传递用户名的问题
嘿,我来帮你搞定登录窗口和主窗口之间的用户名传递问题,先修正代码里的几个关键问题,再给出清晰的解决方案:
首先修正原代码中的明显错误
你的Login类里写了两个完全相同的__init__方法,这会导致第二个方法覆盖第一个,运行时只有第二个__init__生效,得删掉重复的那一段。
传递用户名的几种可行方案
方案1:通过主窗口构造函数直接传参(最直接简单)
修改Main类的构造函数,让它接收用户名参数,在登录成功时创建Main实例时把用户名传进去。
方案2:优化数据库查询逻辑
原代码里分开查询所有用户名和密码再匹配的方式效率低且不安全,建议直接根据输入的用户名查询对应的密码,这样更高效也更符合数据库操作规范。
修正后的完整代码
import os import sys from pathlib import Path from PyQt5.QtWidgets import QMainWindow, QApplication from PyQt5.uic import loadUiType import pymysql # 加载UI文件 UI_PATH = Path(os.path.dirname(__file__)) FROM_CLASS, _ = loadUiType(str(UI_PATH / "Main_rfi-design2.ui")) FROM_CLASS2, _ = loadUiType(str(UI_PATH / "login_rfi.ui")) class Login(QMainWindow, FROM_CLASS2): def __init__(self, parent=None): super(Login, self).__init__(parent) QMainWindow.__init__(self) self.setupUi(self) self.btn_login.clicked.connect(self.handel_login) self.window2 = None def handel_login(self): # 连接数据库 self.db = pymysql.connect(host="localhost", user="root", passwd="", db="db_co") self.cur = self.db.cursor() self.user_name = self.lineEdit.text().strip() self.password = self.lineEdit_16.text().strip() # 优化查询:直接根据用户名查找对应的密码 sql = '''SELECT pass FROM users WHERE user_name = %s''' self.cur.execute(sql, (self.user_name,)) result = self.cur.fetchone() if result: # 查到用户,验证密码 if self.password == result[0]: # 创建主窗口实例并传入用户名 self.window2 = Main(current_user=self.user_name) self.close() self.window2.show() else: self.label.setText('Please check User Name or Password...') else: self.label.setText('User name does not exist...') print('Current user is: ' + self.user_name) # 关闭数据库连接 self.cur.close() self.db.close() class Main(QMainWindow, FROM_CLASS): def __init__(self, current_user=None, parent=None): super(Main, self).__init__(parent) QMainWindow.__init__(self) self.setupUi(self) # 保存传递过来的用户名 self.current_user = current_user # 可以在这里使用用户名,比如显示在界面上 if self.current_user: print(f"Welcome, {self.current_user}!") # 假设你有个label用来显示用户名,比如: # self.user_label.setText(f"当前用户:{self.current_user}") # 初始化其他功能 self.initUI() self.handel_button() def initUI(self): # 你的初始化逻辑 pass def handel_button(self): # 你的按钮处理逻辑 pass if __name__ == "__main__": app = QApplication(sys.argv) login_window = Login() login_window.show() sys.exit(app.exec_())
关键修改点说明
- 删除重复的
__init__方法:保证Login类初始化逻辑正确 - 优化数据库查询:避免全表扫描,只查询当前输入用户的密码,更高效安全
- 主窗口构造函数接收用户名:在创建Main实例时通过
Main(current_user=self.user_name)传递用户名,Main类中保存并使用该值 - 关闭数据库连接:查询完成后关闭游标和连接,避免资源泄漏
可选方案:使用Qt信号与槽(适合复杂场景)
如果后续需要更灵活的通信(比如登录后动态更新主窗口内容),可以给Login类定义一个信号,在登录成功时发射该信号,主窗口监听这个信号接收用户名:
在Login类中添加信号:
from PyQt5.QtCore import pyqtSignal class Login(QMainWindow, FROM_CLASS2): # 定义传递用户名的信号 login_success = pyqtSignal(str) def __init__(self, parent=None): super().__init__(parent) # ... 其他初始化代码 def handel_login(self): # ... 验证逻辑 if self.password == result[0]: self.login_success.emit(self.user_name) self.close()
然后在主程序中连接信号:
if __name__ == "__main__": app = QApplication(sys.argv) login_window = Login() main_window = Main() def on_login_success(username): main_window.current_user = username main_window.show() login_window.login_success.connect(on_login_success) login_window.show() sys.exit(app.exec_())
这个方式适合登录窗口和主窗口需要更松散耦合的场景。
内容的提问来源于stack exchange,提问作者Haitham I. AbuSalem
相关产品推荐
相关产品推荐

