Wednesday, February 8, 2023

Python PyQt program and MySQL as a backend with a Model View Controller (MVC) design pattern

Introduction

The Model View Controller (MVC) design pattern is a widely used pattern for designing graphical user interfaces. It separates the data (model), the presentation (view), and the control (controller) of an application. This pattern allows for a clear separation of concerns and provides a more organized and maintainable codebase.

In this article, we will be discussing a Python PyQt program that uses MySQL as a backend, utilizing the MVC design pattern. This program is designed to display data from a database in a data grid, and show the details of a selected row in a QTextEdit widget.


Program Overview

The program consists of three main components: the Model, the View, and the Controller. The Model class is responsible for retrieving the data from the database and storing it. The View class displays the data in a data grid and the Controller class acts as the mediator between the Model and View, handling the interactions between them.


The Model

The Model class is responsible for retrieving the data from the database and storing it. It connects to the database, fetches the data, and closes the connection. The data is then stored in a variable for later use. This class also overrides the rowCount and columnCount methods to return the number of rows and columns in the data, respectively. The data method returns the data at a given index.


The View

The View class is responsible for displaying the data in a data grid. It is a QTableView widget and sets the selection behavior and mode to allow for the selection of rows. The EditTriggers property is set to NoEditTriggers to prevent the user from editing the data in the grid.


The Detail View

The DetailView class displays the details of a selected row in a QTextEdit widget. It is set to be read-only to prevent the user from modifying the details.


The Controller

The Controller class acts as the mediator between the Model and View, handling the interactions between them. It creates instances of the Model and View classes and sets the View's model to be the Model. The Controller class also defines the showDetails method, which is called when a row in the data grid is selected. This method retrieves the data for the selected row and sets it as the text in the DetailView widget.


Conclusion

This Python PyQt program and MySQL as a backend with a Model View Controller (MVC) design pattern provides a clear and organized way to display data from a database. The separation of concerns in the MVC pattern makes the code more maintainable and easier to understand. Whether you are a beginner or an experienced programmer, this program can serve as a useful example of how to use the MVC pattern in your own projects. 


Here is the code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import mysql.connector

class Model(QtCore.QAbstractTableModel):
    def __init__(self, parent=None):
        super(Model, self).__init__(parent)
        self.loadData()
        
    def loadData(self):
        self.db = mysql.connector.connect(
            host="localhost",
            user="root",
            password="password",
            database="database"
        )
        self.cursor = self.db.cursor()
        self.cursor.execute("SELECT * FROM table")
        self.data = self.cursor.fetchall()
        self.cursor.close()
        self.db.close()
    
    def rowCount(self, parent=QtCore.QModelIndex()):
        return len(self.data)
    
    def columnCount(self, parent=QtCore.QModelIndex()):
        return len(self.data[0])
    
    def data(self, index, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            row = index.row()
            column = index.column()
            return self.data[row][column]

class View(QtWidgets.QTableView):
    def __init__(self, parent=None):
        super(View, self).__init__(parent)
        self.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)
        self.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
        self.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)

class DetailView(QtWidgets.QTextEdit):
    def __init__(self, parent=None):
        super(DetailView, self).__init__(parent)
        self.setReadOnly(True)

class Controller(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Controller, self).__init__(parent)
        self.model = Model(self)
        self.view = View(self)
        self.view.setModel(self.model)
        self.view.clicked.connect(self.showDetails)
        self.detail_view = DetailView(self)
        layout = QtWidgets.QVBoxLayout(self)
        layout.addWidget(self.view)
        layout.addWidget(self.detail_view)
        
    def showDetails(self, index):
        row = index.row()
        details = ",".join([str(x) for x in self.model.data[row]])
        self.detail_view.setPlainText(details)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    controller = Controller()
   

No comments:

Post a Comment