点击QRadioButton时Python崩溃,无法加载数据库球员列表到QListWidget
我帮你梳理了代码里几个导致崩溃的核心问题,逐个修复后就能正常运行了:
1. 信号与槽的参数不匹配
QButtonGroup的buttonToggled信号会传递两个参数:被切换的按钮对象和是否被选中的布尔值,但你的showList函数只定义了一个不相关的MainWindow参数,这会直接触发参数不匹配的致命错误。
修改showList的函数签名,并且只在按钮被选中时执行逻辑(避免切换时重复触发两次):
def showList(self, button, checked): if not checked: return # 只处理按钮被选中的情况,忽略取消选中的信号 # 后续逻辑...
2. 数据库查询结果处理错误
cur.fetchall()返回的是元组列表(比如[('PlayerA',), ('PlayerB',)]),而listWidget.addItems()接收的是字符串序列。你现在用addItems(row)会把元组里的每个字符当成单独的列表项,这不仅不符合预期,还可能引发内部错误。
应该改用addItem()并取出元组的第一个元素:
records = self.cur.fetchall() self.listWidget.clear() for row in records: self.listWidget.addItem(row[0]) # 取出元组中的球员名称 # 不需要调用update(),addItem/clear会自动刷新界面
3. 数据库连接的线程安全问题
你在全局初始化了数据库连接和游标,但PyQt的UI操作在主线程,全局连接可能会因为线程上下文冲突导致崩溃。建议把数据库连接移到类内部,比如在自定义窗口类中初始化:
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) # 初始化数据库连接 self.db = sqlite3.connect("fantcktdb.db") self.cur = self.db.cursor() def closeEvent(self, event): # 窗口关闭时关闭数据库连接 self.cur.close() self.db.close() event.accept()
4. 添加异常捕获避免崩溃
为了防止数据库操作出错导致程序崩溃,可以在查询逻辑中加入异常捕获:
def showList(self, button, checked): if not checked: return self.listWidget.clear() try: if button == self.batRadio: self.cur.execute('''SELECT Player FROM stats WHERE Ctg='BAT';''') elif button == self.bowRadio: self.cur.execute('''SELECT Player FROM stats WHERE Ctg='BOW';''') elif button == self.arRadio: self.cur.execute('''SELECT Player FROM stats WHERE Ctg='AR';''') elif button == self.wkRadio: self.cur.execute('''SELECT Player FROM stats WHERE Ctg='WK';''') records = self.cur.fetchall() for row in records: self.listWidget.addItem(row[0]) except Exception as e: print(f"数据库查询错误: {e}")
完整修复后的代码
整合所有修改后的完整代码如下:
from PyQt5 import QtCore, QtGui, QtWidgets import sqlite3 class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 600) self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) self.gridLayout.setObjectName("gridLayout") self.frame = QtWidgets.QFrame(self.centralwidget) self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel) self.frame.setFrameShadow(QtWidgets.QFrame.Raised) self.frame.setObjectName("frame") self.gridLayout_2 = QtWidgets.QGridLayout(self.frame) self.gridLayout_2.setObjectName("gridLayout_2") self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.wkRadio = QtWidgets.QRadioButton(self.frame) self.wkRadio.setObjectName("wkRadio") self.buttonGroup = QtWidgets.QButtonGroup(MainWindow) self.buttonGroup.setObjectName("buttonGroup") self.buttonGroup.addButton(self.wkRadio) self.verticalLayout.addWidget(self.wkRadio) self.arRadio = QtWidgets.QRadioButton(self.frame) self.arRadio.setObjectName("arRadio") self.buttonGroup.addButton(self.arRadio) self.verticalLayout.addWidget(self.arRadio) self.bowRadio = QtWidgets.QRadioButton(self.frame) self.bowRadio.setObjectName("bowRadio") self.buttonGroup.addButton(self.bowRadio) self.verticalLayout.addWidget(self.bowRadio) self.batRadio = QtWidgets.QRadioButton(self.frame) self.batRadio.setObjectName("batRadio") self.buttonGroup.addButton(self.batRadio) self.verticalLayout.addWidget(self.batRadio) self.buttonGroup.buttonToggled.connect(self.showList) self.listWidget = QtWidgets.QListWidget(self.frame) self.listWidget.setObjectName("listWidget") self.verticalLayout.addWidget(self.listWidget) self.gridLayout_2.addLayout(self.verticalLayout, 0, 0, 1, 1) self.gridLayout.addWidget(self.frame, 0, 0, 1, 1) MainWindow.setCentralWidget(self.centralwidget) self.menubar = QtWidgets.QMenuBar(MainWindow) self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26)) self.menubar.setObjectName("menubar") MainWindow.setMenuBar(self.menubar) self.statusbar = QtWidgets.QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QtCore.QMetaObject.connectSlotsByName(MainWindow) def showList(self, button, checked): if not checked: return self.listWidget.clear() try: if button == self.batRadio: self.cur.execute('''SELECT Player FROM stats WHERE Ctg='BAT';''') elif button == self.bowRadio: self.cur.execute('''SELECT Player FROM stats WHERE Ctg='BOW';''') elif button == self.arRadio: self.cur.execute('''SELECT Player FROM stats WHERE Ctg='AR';''') elif button == self.wkRadio: self.cur.execute('''SELECT Player FROM stats WHERE Ctg='WK';''') records = self.cur.fetchall() for row in records: self.listWidget.addItem(row[0]) except Exception as e: print(f"错误: {e}") def retranslateUi(self, MainWindow): _translate = QtCore.QCoreApplication.translate MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow")) self.wkRadio.setText(_translate("MainWindow", "WK")) self.arRadio.setText(_translate("MainWindow", "AR")) self.bowRadio.setText(_translate("MainWindow", "BOW")) self.batRadio.setText(_translate("MainWindow", "BAT")) class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow): def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) # 初始化数据库连接 self.db = sqlite3.connect("fantcktdb.db") self.cur = self.db.cursor() def closeEvent(self, event): # 关闭数据库连接 self.cur.close() self.db.close() event.accept() if __name__ == "__main__": import sys app = QtWidgets.QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_())
这些修改应该能彻底解决你遇到的崩溃问题,同时让代码更健壮易维护。
内容的提问来源于stack exchange,提问作者Tejaswini Nimbalkar
相关产品推荐
相关产品推荐

