Search code examples
pythonmysqlpyqtpyqt4qtablewidget

update table with database every time interval


I'm trying to make a paint event that updates my GUI every 1 minute.. here is the code for main.py :

# -*- coding: utf-8 -*-

from PyQt4 import QtGui, QtCore
import sys
import main3, report
import MySQLdb


db = MySQLdb.connect(host="localhost",    # your host, usually localhost
                     user="root",         # your username
                     passwd="**************",  # your password
                     db="health",
                     port=3306)        # name of the data base

cur = db.cursor()


class report(QtGui.QMainWindow, report.Ui_Report1):
    def __init__(self, p_id, parent=None):
        super(report, self).__init__(parent)
        self.setupUi(self)

        self.lineEdit.setText('ID: ' + str(p_id))
        cur.execute("SELECT * FROM patient WHERE id = '%s'"%(p_id))
        pt_row_report = cur.fetchall()
        for row in pt_row_report:
            pt_name_report = row[1]
            pt_age_report = row[2]
            cur.execute("SELECT * FROM clinic WHERE p_id = '%s'"%(p_id))
            clinic_row = cur.fetchone()
            d_id = clinic_row[2]
            ray_type1 = clinic_row[6]
            ray_type = ray_type1[17:]
            cur.execute("SELECT * FROM staff WHERE id = '%s'"%(d_id))
            staff_row = cur.fetchall()[0]
            doctor_name = staff_row[1]
            doctor_id = staff_row[0]
            self.lineEdit_2.setText('Name: ' + str(pt_name_report))
            self.lineEdit_3.setText('Age: ' + str(pt_age_report))
            self.lineEdit_6.setText(str(ray_type))
            self.lineEdit_7.setText('Dr. ' + str(doctor_name))

            cur.execute("SELECT Name FROM staff WHERE id = 48588")
            ray_dr_name = cur.fetchone()[0]
            self.lineEdit_4.setText('Dr. ' + str(ray_dr_name))
            self.pushButton.clicked.connect(lambda: self.update_report(p_id, ray_type,doctor_id))


    def update_report(self, name, ray, d_id):
        x = self.textEdit.toPlainText()
        sql = "UPDATE clinic SET Extra_Notice = (%s) WHERE p_id=(%s)"
        cur.execute(sql,(x,name))
        db.commit()
        cur.execute("INSERT INTO rays (p_ID, Ray_Type, Report, D_ID, RS_ID) VALUES (%s,%s,%s,%s,%s)", (int(name), ray, x, d_id, 48588))
        db.commit()



    def get_text(self, x):
        x = self.textEdit.text()
        return x


class First(QtGui.QMainWindow, main3.Ui_MainWindow):
    def __init__(self, parent=None):
        super(First, self).__init__(parent)
        self.setupUi(self)
        timer = QtCore.QTimer(self)
        timer.timeout.connect(self.reload_data)
        timer.start(60*1000)
        self.reload_data()


    def reload_data(self):
        self.tableWidget.clear()
        self.tableWidget.setColumnCount(7)

        cur.execute("SELECT * FROM clinic WHERE Extra_Notice LIKE %s",("%{}%".format('x-ray is required'),))
        test_list = cur.fetchall()
        queue = 1
        for row in test_list:
            c_id = row[0]
            p_id = row[1]
            cur.execute("SELECT * FROM patient WHERE id = '%s'"%(p_id))
            pt = cur.fetchall()[0]
            if pt:

                pt_name = pt[1]
                pt_age = pt[2]
                pt_address = pt[4]
                pt_phone = pt[3]


                button = QtGui.QPushButton('Make Operation')
                button.setStyleSheet("background-color: #4f81bc; color: white;")
                button.clicked.connect(lambda checked, p_id=p_id : self.open_report(p_id))

                rowposition = self.tableWidget.rowCount()

                self.tableWidget.insertRow(rowposition)

                for i, val in enumerate([queue, c_id, pt_name, pt_age, pt_address, pt_phone]):
                    self.tableWidget.setItem(rowposition , i , QtGui.QTableWidgetItem(str(val)))
                self.tableWidget.setCellWidget(rowposition , 6, button)
                queue += 1

    def open_report(self, p_id):
        self.child_win = report(p_id)
        self.child_win.show()
        sys.exit(app.exec_())
        return p_id


def main():
    app = QtGui.QApplication(sys.argv)
    app.setStyle('Plastique')
    main = First()
    main.update()
    main.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()   

and here is the code for the design of ui as generated from Qdesign:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'main.ui'
#
# Created: Sun Jul  1 17:18:19 2018
#      by: PyQt4 UI code generator 4.10
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui
import datetime
import MySQLdb
import r_rc
import r_new_rc


db = MySQLdb.connect(host="localhost",    # your host, usually localhost
                     user="root",         # your username
                     passwd="***************",  # your password
                     db="health",
                     port=3306)        # name of the data base

cur = db.cursor()

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)


class AlignDelegate(QtGui.QItemDelegate):
    def paint(self, painter, option, index):
        option.displayAlignment = QtCore.Qt.AlignCenter
        QtGui.QItemDelegate.paint(self, painter, option, index)

class Ui_MainWindow(object):
    date = datetime.datetime.now().strftime ("%d - %m - %Y")

    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(723, 372)
        MainWindow.setStyleSheet(_fromUtf8("background-color: qradialgradient(spread:pad, cx:0.5, cy:0.5, radius:0.5, fx:0.488636, fy:0.506, stop:0.443182 rgba(135, 164, 207, 255), stop:0.9375 rgba(0, 0, 164, 255));"))
        MainWindow.setAnimated(True)
        MainWindow.setDocumentMode(False)
        MainWindow.setUnifiedTitleAndToolBarOnMac(False)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.label2 = QtGui.QLabel(self.centralwidget)
        self.label2.setGeometry(QtCore.QRect(120, 10, 481, 51))
        self.label2.setStyleSheet(_fromUtf8("background-color: #0000a4;color: gray;\n"
"font: 75 18pt \"Arial\";\n"))
        self.label2.setObjectName(_fromUtf8("textEdit"))
        self.label2.setText('                    Analysis & Rays')
        self.lineEdit = QtGui.QLineEdit(self.centralwidget)
        self.lineEdit.setGeometry(QtCore.QRect(210, 70, 321, 31))
        self.lineEdit.setStyleSheet(_fromUtf8("background-color: rgb(255, 255, 255);"))
        self.lineEdit.setObjectName(_fromUtf8("lineEdit"))
        self.lineEdit.setText(self.date)
        self.lineEdit.setReadOnly(True)
        self.tableWidget = QtGui.QTableWidget(self.centralwidget)
        self.tableWidget.setGeometry(QtCore.QRect(10, 120, 701, 231))
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed, QtGui.QSizePolicy.Fixed)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.tableWidget.sizePolicy().hasHeightForWidth())
        self.tableWidget.setSizePolicy(sizePolicy)
        self.tableWidget.setMaximumSize(QtCore.QSize(800, 500))
        self.tableWidget.setStyleSheet(_fromUtf8("background-color: rgb(255, 255, 255);"))
        self.tableWidget.setObjectName(_fromUtf8("tableWidget"))
        self.tableWidget.setItemDelegate(AlignDelegate())
        self.tableWidget.verticalHeader().hide()
        self.tableWidget.setHorizontalHeaderLabels(("Queue number;ID;Name;Age;Address;Phone;Make Operation;").split(";"))
        header = self.tableWidget.horizontalHeader()
        header.setResizeMode(0, QtGui.QHeaderView.Stretch)
        header.setResizeMode(1, QtGui.QHeaderView.ResizeToContents)
        header.setResizeMode(2, QtGui.QHeaderView.ResizeToContents)

        self.label = QtGui.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(640, 0, 31, 51))
        self.label.setObjectName(_fromUtf8("label"))
        #self.label_2 = QtGui.QLabel(self.centralwidget)
        #self.label_2.setGeometry(QtCore.QRect(450, 0, 70, 65))
        #self.label_2.setStyleSheet(_fromUtf8("background-color: rgb(255, 255, 255);"))
        #self.label_2.setObjectName(_fromUtf8("label_2"))
        MainWindow.setCentralWidget(self.centralwidget)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow", None))
        self.label.setText(_translate("MainWindow", "<html><head/><body><p><img src=\":/newPrefix//444.png\"/></p></body></html>", None))
        ##self.label_2.setText(_translate("MainWindow", "<html><head/><body><p><img src=\":/newPrefix/36611129_2021894281460024_9133838233774325760_n.png\"/></p></body></html>", None))

I need to do is to reupdate the tableWidget every one min, the rest of the code is simply the design of other elements in the GUI so that it shows the new item that it fetches from the DB

the code executes normally, but I keep getting this error in the console and the update is not happening

TypeError: paintEvent() takes exactly 1 argument (2 given)

update

I deleted the paint event function and tried to add just a normal timer to the main loop of the code.

as shown in the code above it is working now but keeps adding an empty row every 1 mintute and the loops goes on forever with adding empty rows to the table.


Solution

  • From your comments, you do not want to update the painting, what you want is to reload the data that you get from the database every minute. paintEvent() is a method of widgets that allow to do the painting, and in this case it is not necessary, besides the method update() serves to call that method indirectly, in your case I stress that it is not necessary. What you should do is create a method that is responsible for filling the QTableWidget and calling it using a QTimer.

    class First(QtGui.QMainWindow, main3.Ui_MainWindow):
        def __init__(self, parent=None):
            super(First, self).__init__(parent)
            self.setupUi(self)
            timer = QtCore.QTimer(self)
            timer.timeout.connect(self.reload_data)
            timer.start(60*1000)
            self.reload_data()
    
    
        def reload_data(self):
            print("reload_data")
            self.tableWidget.clear()
            self.tableWidget.setRowCount(0)
            self.tableWidget.setColumnCount(7)
    
            cur.execute("SELECT * FROM clinic WHERE Extra_Notice LIKE %s",("%{}%".format('x-ray is required'),))
            test_list = cur.fetchall()
            queue = 1
            for row in test_list:
                c_id = row[0]
                p_id = row[1]
                cur.execute("SELECT * FROM patient WHERE id = '%s'"%(p_id))
                pt = cur.fetchall()[0]
                print(pt)
                if not pt:
                    continue
    
                pt_name = pt[1]
                pt_age = pt[2]
                pt_address = pt[4]
                pt_phone = pt[3]
    
                button = QtGui.QPushButton('Make Operation')
                button.setStyleSheet("background-color: #4f81bc; color: white;")
                button.clicked.connect(lambda checked, p_id=p_id : self.open_report(p_id))
    
                rowposition = self.tableWidget.rowCount()
    
                self.tableWidget.insertRow(rowposition)
    
                for i, val in enumerate([queue, c_id, pt_name, pt_age, pt_address, pt_phone]):
                    self.tableWidget.setItem(rowposition , i , QtGui.QTableWidgetItem(str(val)))
                self.tableWidget.setCellWidget(rowposition , 6, button)
                queue += 1
    
        def open_report(self, p_id):
            self.child_win = report(p_id)
            self.child_win.show()
            sys.exit(app.exec_())
            return p_id