0

I am developing an installation menu for an application in PyQt5. The directory structure is as follows:

install-menu/
├── app.py
├── controller
│   ├── controller.py
│   ├── __init__.py
│   └── __pycache__
│       ├── controller.cpython-38.pyc
│       └── __init__.cpython-38.pyc
├── model
│   ├── __init__.py
│   ├── model.py
│   └── __pycache__
│       ├── __init__.cpython-38.pyc
│       └── model.cpython-38.pyc
└── view
    ├── __init__.py
    ├── __pycache__
    │   ├── __init__.cpython-38.pyc
    │   └── view.cpython-38.pyc
    └── view.py

I am trying to follow MVC architecture. The code of related files are as below:

  • app.py
#!/usr/bin/env python3
from controller.controller import Installer
from view.view import GUIDisplay
from model.model import parameters
from PyQt5.QtWidgets import QApplication
import sys

# Client code
def main():
    """Main function."""
    # Create an instance of `QApplication`
    qapp = QApplication(sys.argv)
    # Show the installer's GUI
    view = GUIDisplay()
    view.show()
    # Create instances of the model and the controller
    model = parameters()

    #Calling Installer/Controller
    Installer(model=model, view=view)
    # Execute installer's main loop
    sys.exit(qapp.exec_())


if __name__ == "__main__":
    main()
  • controller.py
# Create a Controller class to connect the GUI and the model
class Installer:
    """Installer Controller."""

    def __init__(self, model, view):
        """Controller initializer."""
        self._model = model
        self._view = view
        # Connect signals and slots
        self._connectSignals()

    def _connectSignals(self):
        """Connect signals and slots."""
        self.installBtn = self._view.install
        self.installBtn.clicked.connect(self.printMe)

    def printMe(self):
        """Build functionality for installation of PXE Server"""
        self.pxeValues = self._model.getPxe(self._view)
        print (pxeValues)
  • model.py
# Create a Model to handle the operations
# Define a global error object
ERROR_MSG = "ERROR"

class parameters:
    def __init__(self):
        self.pxeHostname=""
        self.pxeIP=""

    def getPxe(self, view):
        """Evaluate an expression."""
        self.pxeDetails = []
        print ("Read Label Function called.")
        try:
            self.pxeHostname = view.txtPxeHostname.text()
            self.pxeIP = view.txtPxeIP.text()
            self.pxeDetails.append(self.pxeHostname)
            self.pxeDetails.append(self.pxeIP)
        except Exception:
            self.pxeDetails.append(ERROR_MSG)
        return pxeDetails
  • view.py
# Import modules for view to work

# Import QApplication and the required widgets from PyQt5.QtWidgets
from PyQt5.QtCore import Qt
from PyQt5.QtCore import QRect
from PyQt5.QtCore import QMetaObject
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtWidgets import QGridLayout
from PyQt5.QtWidgets import QLineEdit
from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtWidgets import QPushButton
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtWidgets import QWidget
from PyQt5.QtWidgets import QLabel
from PyQt5.QtWidgets import QFormLayout
from PyQt5.QtWidgets import QHBoxLayout
from PyQt5.QtWidgets import QStatusBar

# Create a subclass of QMainWindow to setup the installer's GUI
class GUIDisplay(QMainWindow):
    """Installer's View (GUI)."""

    def __init__(self):
        """View initializer."""
        super().__init__()
        # Set some main window's properties
        QMainWindow.setObjectName(self,"MainWindow")
        QMainWindow.resize(self, 795, 600)
        self.centralwidget = QWidget()
        self.centralwidget.setObjectName("centralwidget")
        # Create the display and the buttons
        self.createDisplay()
        self.createButtons()
        self.menus()
        self.fillPlaceHolders(QMainWindow)
        QMetaObject.connectSlotsByName(self)

    def menus(self):
        menu = self.menuBar()
        # Setting Menu and items
        settings = menu.addMenu("Settings")
        install = settings.addMenu("Install")
        reinstall = settings.addMenu("Reinstall")
        status = settings.addMenu("Status")
       
    def createDisplay(self):
        """Creating display layouts."""
        # Main Heading
        self.mainHeading = QLabel(self.centralwidget)
        self.mainHeading.setGeometry(QRect(350, 20, 141, 20))
        self.mainHeading.setObjectName("mainHeading")
        # PXE Server configuration paramaters and Layouts
        ## Creating main Heading and labels for PXE Server Configurations
        self.pxeConfig = QLabel(self.centralwidget)
        self.pxeConfig.setGeometry(QRect(10, 70, 231, 18))
        self.pxeConfig.setObjectName("pxeConfig")
        ## Adding Form Layout for Hostname and IP for PXE Server
        self.pxeServerLayout = QWidget(self.centralwidget)
        self.pxeServerLayout.setGeometry(QRect(129, 90, 561, 61))
        self.pxeServerLayout.setObjectName("pxeServerLayout")
        self.pxeLayout = QFormLayout(self.pxeServerLayout)
        self.pxeLayout.setContentsMargins(0, 0, 0, 0)
        self.pxeLayout.setObjectName("pxeLayout")
        ## Adding Hostname Labels and TextField for PXE Server
        self.pxeHostname = QLabel(self.pxeServerLayout)
        self.pxeHostname.setObjectName("pxeHostname")
        self.pxeLayout.setWidget(0, QFormLayout.LabelRole, self.pxeHostname)
        self.txtPxeHostname = QLineEdit(self.pxeServerLayout)
        self.txtPxeHostname.setObjectName("txtPxeHostname")
        ## Adding IP Address Labels and TextField for PXE Server
        self.pxeLayout.setWidget(0, QFormLayout.FieldRole, self.txtPxeHostname)
        self.pxeIP = QLabel(self.pxeServerLayout)
        self.pxeIP.setObjectName("pxeIP")
        self.pxeLayout.setWidget(1, QFormLayout.LabelRole, self.pxeIP)
        self.txtPxeIP = QLineEdit(self.pxeServerLayout)
        self.txtPxeIP.setObjectName("txtPxeIP")
        self.pxeLayout.setWidget(1, QFormLayout.FieldRole, self.txtPxeIP)

       

    def createButtons(self):
        """Create the buttons."""
        # Add buttonsLayout to the general layout
        self.horizontalLayoutWidget = QWidget(self.centralwidget)
        self.horizontalLayoutWidget.setGeometry(QRect(133, 500, 561, 31))
        self.horizontalLayoutWidget.setObjectName("horizontalLayoutWidget")
        self.horizontalLayout = QHBoxLayout(self.horizontalLayoutWidget)
        self.horizontalLayout.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.install = QPushButton(self.horizontalLayoutWidget)
        self.install.setObjectName("install")
        self.horizontalLayout.addWidget(self.install)
        self.reinstall = QPushButton(self.horizontalLayoutWidget)
        self.reinstall.setObjectName("reinstall")
        self.horizontalLayout.addWidget(self.reinstall)
        self.status = QPushButton(self.horizontalLayoutWidget)
        self.status.setObjectName("status")
        self.horizontalLayout.addWidget(self.status)
        QMainWindow.setCentralWidget(self, self.centralwidget)
        self.statusbar = QStatusBar()
        self.statusbar.setObjectName("statusbar")
        QMainWindow.setStatusBar(self, self.statusbar)

    def fillPlaceHolders(self, MainWindow):
        _translate = QCoreApplication.translate
        MainWindow.setWindowTitle(self, _translate("MainWindow", "PXE Server Installer"))
        self.mainHeading.setText("Installation Setup")
        self.pxeConfig.setText("PxeBoot Server Configuration:")
        self.pxeHostname.setText("PXE Hostname:")
        self.pxeIP.setText("PXE Server IP:")
        self.install.setText("Install")
        self.reinstall.setText("Reinstall")
        self.status.setText("status")

But clicking on install button the callback function is not firing up. I don't know what is going wrong. Same function should be invoked with menu item on being clicked with same text as on button.

1 Answer 1

2

The problem is simple: you must assign the Installer class object to a variable:

installer = Installer(model=model, view=view)

On the other hand you must change self.pxeDetails to pxeDetails in model.py:

def getPxe(self, view):
    """Evaluate an expression."""
    pxeDetails = []
    print ("Read Label Function called.")
    try:
        self.pxeHostname = view.txtPxeHostname.text()
        self.pxeIP = view.txtPxeIP.text()
        pxeDetails.append(self.pxeHostname)
        pxeDetails.append(self.pxeIP)
    except Exception:
        pxeDetails.append(ERROR_MSG)
    return pxeDetails

and change self.pxeValues to pxeValues in controller.py:

def printMe(self):
    """Build functionality for installation of PXE Server"""
    pxeValues = self._model.getPxe(self._view)
    print (pxeValues)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.