PyQt5和MySQL GUI程序崩溃

w8rqjzmb  于 2022-12-17  发布在  Mysql
关注(0)|答案(1)|浏览(132)

因此,我使用PyQt5为数据库表单制作了一个GUI,它允许您对数据库执行不同的操作。选择、插入、删除、一般查看和清除。清除只是清除GUI表格中显示的数据。
选择、插入、删除和一般视图中的每一个,当按下时,都应该运行它们所连接的相应功能。在这些功能中,它们连接到数据库,运行查询并在表中显示结果。
然而,当我运行GUI并按下一个按钮,如General View,程序停止运行并崩溃,我在IDLE Shell中也没有得到任何追溯或错误报告。
我的代码如下:

from PyQt5 import QtCore, QtGui, QtWidgets
import mysql.connector as mc
from PyQt5.QtWidgets import QTableWidgetItem

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(538, 487)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.verticalLayout = QtWidgets.QVBoxLayout(self.centralwidget)
        self.verticalLayout.setObjectName("verticalLayout")
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.lineCMS = QtWidgets.QLineEdit(self.centralwidget)
        self.lineCMS.setObjectName("lineCMS")
        self.gridLayout_2.addWidget(self.lineCMS, 0, 1, 1, 1)
        self.lineRoom = QtWidgets.QLineEdit(self.centralwidget)
        self.lineRoom.setObjectName("lineRoom")
        self.gridLayout_2.addWidget(self.lineRoom, 3, 1, 1, 1)
        self.CMS = QtWidgets.QLabel(self.centralwidget)
        self.CMS.setObjectName("CMS")
        self.gridLayout_2.addWidget(self.CMS, 0, 0, 1, 1)
        self.lineName = QtWidgets.QLineEdit(self.centralwidget)
        self.lineName.setObjectName("lineName")
        self.gridLayout_2.addWidget(self.lineName, 1, 1, 1, 1)
        self.Room = QtWidgets.QLabel(self.centralwidget)
        self.Room.setObjectName("Room")
        self.gridLayout_2.addWidget(self.Room, 3, 0, 1, 1)
        self.Department = QtWidgets.QLabel(self.centralwidget)
        self.Department.setObjectName("Department")
        self.gridLayout_2.addWidget(self.Department, 2, 0, 1, 1)
        self.Name = QtWidgets.QLabel(self.centralwidget)
        self.Name.setObjectName("Name")
        self.gridLayout_2.addWidget(self.Name, 1, 0, 1, 1)
        self.lineDepartment = QtWidgets.QLineEdit(self.centralwidget)
        self.lineDepartment.setObjectName("lineDepartment")
        self.gridLayout_2.addWidget(self.lineDepartment, 2, 1, 1, 1)
        self.lineDOB = QtWidgets.QLineEdit(self.centralwidget)
        self.lineDOB.setObjectName("lineDOB")
        self.gridLayout_2.addWidget(self.lineDOB, 4, 1, 1, 1)
        self.DOB = QtWidgets.QLabel(self.centralwidget)
        self.DOB.setObjectName("DOB")
        self.gridLayout_2.addWidget(self.DOB, 4, 0, 1, 1)
        self.verticalLayout.addLayout(self.gridLayout_2)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.Select = QtWidgets.QPushButton(self.centralwidget)
        self.Select.setObjectName("Select")
        self.horizontalLayout.addWidget(self.Select)
        self.line = QtWidgets.QFrame(self.centralwidget)
        self.line.setFrameShape(QtWidgets.QFrame.VLine)
        self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line.setObjectName("line")
        self.horizontalLayout.addWidget(self.line)
        self.Insert = QtWidgets.QPushButton(self.centralwidget)
        self.Insert.setObjectName("Insert")
        self.horizontalLayout.addWidget(self.Insert)
        self.line_2 = QtWidgets.QFrame(self.centralwidget)
        self.line_2.setFrameShape(QtWidgets.QFrame.VLine)
        self.line_2.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_2.setObjectName("line_2")
        self.horizontalLayout.addWidget(self.line_2)
        self.Delete = QtWidgets.QPushButton(self.centralwidget)
        self.Delete.setObjectName("Delete")
        self.horizontalLayout.addWidget(self.Delete)
        self.line_3 = QtWidgets.QFrame(self.centralwidget)
        self.line_3.setFrameShape(QtWidgets.QFrame.VLine)
        self.line_3.setFrameShadow(QtWidgets.QFrame.Sunken)
        self.line_3.setObjectName("line_3")
        self.horizontalLayout.addWidget(self.line_3)
        self.Clear = QtWidgets.QPushButton(self.centralwidget)
        self.Clear.setObjectName("Clear")
        self.horizontalLayout.addWidget(self.Clear)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.table = QtWidgets.QTableWidget(self.centralwidget)
        self.table.setObjectName("table")
        self.table.setColumnCount(5)
        self.table.setRowCount(0)
        item = QtWidgets.QTableWidgetItem()
        self.table.setHorizontalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.table.setHorizontalHeaderItem(1, item)
        item = QtWidgets.QTableWidgetItem()
        self.table.setHorizontalHeaderItem(2, item)
        item = QtWidgets.QTableWidgetItem()
        self.table.setHorizontalHeaderItem(3, item)
        item = QtWidgets.QTableWidgetItem()
        self.table.setHorizontalHeaderItem(4, item)
        self.verticalLayout.addWidget(self.table)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        self.generalView = QtWidgets.QPushButton(self.centralwidget)
        self.generalView.setObjectName("generalView")
        self.verticalLayout.addWidget(self.generalView)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 538, 21))
        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)
        self.Select.clicked.connect(self.select)
        self.Insert.clicked.connect(self.insert)
        self.Delete.clicked.connect(self.delete)
        self.generalView.clicked.connect(self.view)
        self.Clear.clicked.connect(self.clear)
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Student"))
        self.CMS.setText(_translate("MainWindow", "CMS"))
        self.Room.setText(_translate("MainWindow", "Room No."))
        self.Department.setText(_translate("MainWindow", "Department"))
        self.Name.setText(_translate("MainWindow", "Name"))
        self.DOB.setText(_translate("MainWindow", "Date of Birth"))
        self.Select.setText(_translate("MainWindow", "SELECT"))
        self.Insert.setText(_translate("MainWindow", "INSERT"))
        self.Delete.setText(_translate("MainWindow", "DELETE"))
        self.Clear.setText(_translate("MainWindow", "CLEAR"))
        item = self.table.horizontalHeaderItem(0)
        item.setText(_translate("MainWindow", "CMS"))
        item = self.table.horizontalHeaderItem(1)
        item.setText(_translate("MainWindow", "Name"))
        item = self.table.horizontalHeaderItem(2)
        item.setText(_translate("MainWindow", "Department"))
        item = self.table.horizontalHeaderItem(3)
        item.setText(_translate("MainWindow", "Room No."))
        item = self.table.horizontalHeaderItem(4)
        item.setText(_translate("MainWindow", "Date of Birth"))
        self.generalView.setText(_translate("MainWindow", "GENERAL VIEW"))
        
    def select():
        try:
            self.table.setRowCount(0)
            QCMS = self.lineCMS.text() + "%"
            QDepartment = self.lineDepartment.text() + "%"
            QName = self.lineName.text() + "%"
            QRoom = self.lineRoom.text() + "%"
            QDOB = self.lineDOB.text() + "%"

            mydb = mc.connect(host="localhost",user="root",password="",database="sakila")
            mycursor = mydb.cursor()
            selectQuery = "SELECT * FROM Student WHERE CMS like '{}' and Department like '{}' and Name like '{}' and RoomNo like '{}' and DateOfBirth like '{}'".format(QCMS, QDepartment, QName, QRoom, QDOB)
            mycursor.execute(selectQuery)
            queryResult = mycursor.fetchall()
            for row_number, row_data in enumerate(queryResult):
                self.table.insertRow(row_number)
                for column_number, data in enumerate(row_data):
                    self.table.setItem(row_number,column_number,QTableWidgetItem(str(data)))
            
        except mc.Error as e:
            print("Error!")

    def insert():
        try:
            self.table.setRowCount(0)
            QCMS = self.lineCMS.text() + "%"
            QDepartment = self.lineDepartment.text() + "%"
            QName = self.lineName.text() + "%"
            QRoom = self.lineRoom.text() + "%"
            QDOB = self.lineDOB.text() + "%"

            mydb = mc.connect(host="localhost",user="root",password="",database="sakila")
            mycursor = mydb.cursor()
            insertQuery = "INSERT INTO Student Values({}, '{}', '{}', {}, '{}')".format(QCMS, QName, QDepartment, QRoom, QDOB)
            triggerQuery = "SELECT * FROM Student WHERE CMS like '{}' and Department like '{}' and Name like '{}' and RoomNo like '{}' and DateOfBirth like '{}'".format(QCMS, QDepartment, QName, QRoom, QDOB)
            mycursor.execute(insertQuery)
            insertResult = mycursor.fetchall()
            mycursor.execute(triggerQuery)
            triggerResult = mycursor.fetchall()
            for row_number, row_data in enumerate(triggerResult):
                self.table.insertRow(row_number)
                for column_number, data in enumerate(row_data):
                    self.table.setItem(row_number,column_number,QTableWidgetItem(str(data)))
            
        except mc.Error as e:
            print("Error!")

    def delete():
        try:
            self.table.setRowCount(0)
            QCMS = self.lineCMS.text() + "%"
            QDepartment = self.lineDepartment.text() + "%"
            QName = self.lineName.text() + "%"
            QRoom = self.lineRoom.text() + "%"
            QDOB = self.lineDOB.text() + "%"

            mydb = mc.connect(host="localhost",user="root",password="",database="sakila")
            mycursor = mydb.cursor()
            deleteQuery = "DELETE FROM Student WHERE CMS like '{}' and Department like '{}' and Name like '{}' and RoomNo like '{}' and DateOfBirth like '{}'".format(QCMS, QDepartment, QName, QRoom, QDOB)
            triggerQuery = "SELECT * FROM Student WHERE CMS like '{}' and Department like '{}' and Name like '{}' and RoomNo like '{}' and DateOfBirth like '{}'".format(QCMS, QDepartment, QName, QRoom, QDOB)
            mycursor.execute(deleteQuery)
            deleteResult = mycursor.fetchall()
            mycursor.execute(triggerQuery)
            triggerResult = mycursor.fetchall()
            for row_number, row_data in enumerate(triggerResult):
                self.table.insertRow(row_number)
                for column_number, data in enumerate(row_data):
                    self.table.setItem(row_number,column_number,QTableWidgetItem(str(data)))
            
        except mc.Error as e:
            print("Error!")

    def view():
        try:
            self.table.setRowCount(0)
            

            mydb = mc.connect(host="localhost",user="root",password="",database="sakila")
            mycursor = mydb.cursor()
            query = "SELECT * FROM Student"
            mycursor.execute(query)
            queryResult = mycursor.fetchall()
            
            
            for row_number, row_data in enumerate(queryResult):
                self.table.insertRow(row_number)
                for column_number, data in enumerate(row_data):
                    self.table.setItem(row_number,column_number,QTableWidgetItem(str(data)))
            
        except mc.Error as e:
            print("Error!")

    def clear():
        self.table.setRowCount(0)
    

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

想不出任何与我现在的处境有关的事情。

4nkexdtk

4nkexdtk1#

我最好的猜测是这是因为你没有在这个程序中使用任何线程。
当你点击一个按钮时,处理GUI事件(鼠标事件,窗口更新)的主事件循环被锁定,因为它正在处理你的按钮代码。这使得GUI看起来被冻结或崩溃(没有响应),因为事件循环忙碌其他事情。
使用PyQt5需要一些概念,线程、信号和插槽是两个核心概念。
线程是与主代码并行运行的代码,它们共享相同的代码空间,因此可以访问相似的变量。
信号和插槽是在主线程和其他正在运行的线程之间传递信息的一种方式。
在您的代码中,您将需要创建一个如下所示的线程类:

class ViewThread(QThread):
    # This is a signal when it is emitted it will send along data of type 'list' 
    query_finished_signal = pyqtSignal(list)
    
    def __init__(self):
        super().__init__()

    def run(self):
        # Here you would put the code to execute your SQL and 
        # get the data returned from the SQL fetch statement put in a 
        # list of lists called query_results.
        # NOTE: You'll need to make the instances of your SQL cursor here so 
        # everything is within the scope of this thread class.
        
        # Here we emit the signal, which will emit query_results to our 
        # connected slot.
        self.query_finished_signal.emit(query_results)
        self.finished.emit()

然后在Ui_MainWindow类中,让view方法启动线程,然后有一个新方法set_view,它只执行主事件循环负责更新的操作。

def __init__(self):

    # vvv keep everything else just add this vvv
    
    #Create an instance of the custom QThread
    self.view_thread = ViewThread()
    
    #This is where we connect the signal, when it is emitted it will send the data to the method  self.set_view
    self.view_thread.query_finished_signal.connect(self.set_view) 

def view(self):
    try:      
        self.view_thread.start() 
    except mc.Error as e:
        print("Error!") 
        
def set_view(self, queryResult=None): #queryResult is a slot which will contain the data emitted from the signal connected to this method
    if queryResult:
        self.table.setRowCount(0)
        for row_number, row_data in enumerate(queryResult):
            self.table.insertRow(row_number)
            for column_number, data in enumerate(row_data):
                self.table.setItem(row_number,column_number,QTableWidgetItem(str(data)))

所有这些的要点是你的事件循环只需要用它给出的数据更新表,这相对较快,但它不需要在你收集信息时冻结GUI。另一个注意,GUI小部件不能通过线程修改,所以像self.lineedit.setText(“Hello”)这样的操作在线程中不起作用,它需要由主线程完成。
注意:此代码仅作为示例,不能作为工作代码复制和粘贴。
我建议在你当前的图形用户界面中,点击一个按钮,如果图形用户界面冻结了,就等它出来,看看它最终是否会再次响应。这就是你知道你需要实现这个解决方案的方法。我希望这对你有帮助:)

相关问题