Writie a PyQT5 Plugin in QGIS (Check ComboBox Value)

Heads up! You've already completed this tutorial.

yuriyrogalski11143 | 2021-05-11 11:45:54 UTC | #1

Hello dear Python Community,

its my first expecience to write a QGIS Plugin with PyQT5. With Plugin Builder i allready Set up the Development Folder and here i have those 3 Files (posted with the Code below) which i can open and execute with Atom and run in QGIS

SPBIM.py (as I understand the main File for writing my App) SPBIM_dialog.py (this File it tells me loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer SPBIM_dialog_base.py (File which was converted converted in cmd line with pyuic5 -x Plugin_dialog_base.ui -o Plugin_dialog_base.py - If i hadn't used the Qt Designer i could have Set up the Interface in here, but not sure the purpose of this File - if i have to add sth here

I have only a ComboBox and a Button Box Object: comboBox Class: QComboBox Object: button_box Class: QDialogButtonBox

The purpose of this Plugin (which is allready implemented in QGIS) is to Check the Values (5 Values set up in QtDesigner) the User activated/ picked in the Combobox !!!

Depending on the Value chosen - a bunch of more Python Code (5 different/ other Python Files) should be implemented/ executed/ run) - from File / in a Function?!

Create GUI Applications with Python & Qt5 by Martin Fitzpatrick — (PyQt5 Edition) The hands-on guide to making apps with Python — Over 10,000 copies sold!

More info Get the book

i can activate self.comboBox in Plugin_dialog_base.py File (but not in SPBIM.py File)

Thank you for advise / hints help. Really trying to get this work done!

From other Forums i found the hint (but don't know how to implement this idea in the SPBIM_dialog.py File) Your "check boxes" don't work because you're putting your lines in the wrong place (run method). However, you need first to declare objects in init method for connecting them to a 'change_status' function (preferably one for each check box). I'm going to exemplify this only for "Interpretation" Check Box.

QGIS environment tells me in SPBIM.py it can't find my both Elemenets (combo_box, button_box) !!!

File: SPBIM.py

python
from qgis.PyQt.QtCore import QSettings, QTranslator, QCoreApplication
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAction

# Initialize Qt resources from file resources.py
from .resources import *
# Import the code for the dialog
from .SPBIM_dialog import SPBIMDialog
import os.path



class SPBIM:
    """QGIS Plugin Implementation."""


def __init__(self, iface):
    """Constructor.

    :param iface: An interface instance that will be passed to this class
        which provides the hook by which you can manipulate the QGIS
        application at run time.
    :type iface: QgsInterface
    """
    # Save reference to the QGIS interface
    self.iface = iface
    # initialize plugin directory
    self.plugin_dir = os.path.dirname(__file__)
    # initialize locale
    locale = QSettings().value('locale/userLocale')[0:2]
    locale_path = os.path.join(
        self.plugin_dir,
        'i18n',
        'SPBIM_{}.qm'.format(locale))

    if os.path.exists(locale_path):
        self.translator = QTranslator()
        self.translator.load(locale_path)
        QCoreApplication.installTranslator(self.translator)

    # Declare instance attributes
    self.actions = []
    self.menu = self.tr(u'&SPBIM')

    # Check if plugin was started the first time in current QGIS session
    # Must be set in initGui() to survive plugin reloads
    self.first_start = None

# noinspection PyMethodMayBeStatic
def tr(self, message):
    """Get the translation for a string using Qt translation API.

    We implement this ourselves since we do not inherit QObject.

    :param message: String for translation.
    :type message: str, QString

    :returns: Translated version of message.
    :rtype: QString
    """
    # noinspection PyTypeChecker,PyArgumentList,PyCallByClass
    return QCoreApplication.translate('SPBIM', message)


def add_action(
    self,
    icon_path,
    text,
    callback,
    enabled_flag=True,
    add_to_menu=True,
    add_to_toolbar=True,
    status_tip=None,
    whats_this=None,
    parent=None):
    """Add a toolbar icon to the toolbar.

    :param icon_path: Path to the icon for this action. Can be a resource
        path (e.g. ':/plugins/foo/bar.png') or a normal file system path.
    :type icon_path: str

    :param text: Text that should be shown in menu items for this action.
    :type text: str

    :param callback: Function to be called when the action is triggered.
    :type callback: function

    :param enabled_flag: A flag indicating if the action should be enabled
        by default. Defaults to True.
    :type enabled_flag: bool

    :param add_to_menu: Flag indicating whether the action should also
        be added to the menu. Defaults to True.
    :type add_to_menu: bool

    :param add_to_toolbar: Flag indicating whether the action should also
        be added to the toolbar. Defaults to True.
    :type add_to_toolbar: bool

    :param status_tip: Optional text to show in a popup when mouse pointer
        hovers over the action.
    :type status_tip: str

    :param parent: Parent widget for the new action. Defaults None.
    :type parent: QWidget

    :param whats_this: Optional text to show in the status bar when the
        mouse pointer hovers over the action.

    :returns: The action that was created. Note that the action is also
        added to self.actions list.
    :rtype: QAction
    """

    icon = QIcon(icon_path)
    action = QAction(icon, text, parent)
    action.triggered.connect(callback)
    action.setEnabled(enabled_flag)

    if status_tip is not None:
        action.setStatusTip(status_tip)

    if whats_this is not None:
        action.setWhatsThis(whats_this)

    if add_to_toolbar:
        # Adds plugin icon to Plugins toolbar
        self.iface.addToolBarIcon(action)

    if add_to_menu:
        self.iface.addPluginToMenu(
            self.menu,
            action)

    self.actions.append(action)

    return action

def initGui(self):
    """Create the menu entries and toolbar icons inside the QGIS GUI."""

    icon_path = ':/plugins/SPBIM/icon.png'
    self.add_action(
        icon_path,
        text=self.tr(u'SPBIM'),
        callback=self.run,
        parent=self.iface.mainWindow())

    # will be set False in run()
    self.first_start = True





def unload(self):
    """Removes the plugin menu item and icon from QGIS GUI."""

    print("UNLOADING Plugin")


    for action in self.actions:
        self.iface.removePluginMenu(
            self.tr(u'&SPBIM'),
            action)
        self.iface.removeToolBarIcon(action)







def run(self):
    """Run method that performs all the real work"""

    print("STARTING Plugin")



    # Create the dialog with elements (after translation) and keep reference
    # Only create GUI ONCE in callback, so that it will only load when the plugin is started
    if self.first_start == True:
        self.first_start = False
        self.dlg = SPBIMDialog()

    # show the dialog
    self.dlg.show()
    # Run the dialog event loop
    result = self.dlg.exec_()
    # See if OK was pressed
    if result:
        # Do something useful here - delete the line containing pass and
        # substitute with your code.

        #
        #

        pass


    print("STARTING Plugin")

File: SPBIM_dialog.py

python
import os

from qgis.PyQt import uic
from qgis.PyQt import QtWidgets

# This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer
FORM_CLASS, _ = uic.loadUiType(os.path.join(
    os.path.dirname(__file__), 'SPBIM_dialog_base.ui'))


class SPBIMDialog(QtWidgets.QDialog, FORM_CLASS):
    def __init__(self, parent=None):
        """Constructor."""
        super().__init__(parent)
        # Set up the user interface from Designer through FORM_CLASS.
        # After self.setupUi() you can access any designer object by doing
        # self.<objectname>, and you can use autoconnect slots - see
        # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
        # #widgets-and-dialogs-with-auto-connect
        self.setupUi(self)

File: SPBIM_dialog_base.py

python
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_SPBIMDialogBase(object):
    def setupUi(self, SPBIMDialogBase):
        SPBIMDialogBase.setObjectName("SPBIMDialogBase")
        SPBIMDialogBase.resize(613, 184)
        self.gridLayout = QtWidgets.QGridLayout(SPBIMDialogBase)
        self.gridLayout.setObjectName("gridLayout")
        spacerItem = QtWidgets.QSpacerItem(20, 72, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
        self.gridLayout.addItem(spacerItem, 2, 0, 1, 1)
        self.button_box = QtWidgets.QDialogButtonBox(SPBIMDialogBase)
        self.button_box.setOrientation(QtCore.Qt.Horizontal)
        self.button_box.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
        self.button_box.setObjectName("button_box")
        self.gridLayout.addWidget(self.button_box, 3, 3, 1, 1)
        self.label = QtWidgets.QLabel(SPBIMDialogBase)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 0, 0, 1, 1)
        self.comboBox = QtWidgets.QComboBox(SPBIMDialogBase)
        self.comboBox.setObjectName("comboBox")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.comboBox.addItem("")
        self.gridLayout.addWidget(self.comboBox, 1, 0, 1, 1)
        spacerItem1 = QtWidgets.QSpacerItem(225, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(spacerItem1, 3, 2, 1, 1)
        spacerItem2 = QtWidgets.QSpacerItem(228, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
        self.gridLayout.addItem(spacerItem2, 1, 1, 1, 1)

        self.retranslateUi(SPBIMDialogBase)
        self.button_box.accepted.connect(SPBIMDialogBase.accept)
        self.button_box.rejected.connect(SPBIMDialogBase.reject)
        QtCore.QMetaObject.connectSlotsByName(SPBIMDialogBase)

    def retranslateUi(self, SPBIMDialogBase):
        _translate = QtCore.QCoreApplication.translate
        SPBIMDialogBase.setWindowTitle(_translate("SPBIMDialogBase", "SPBIM"))
        self.label.setText(_translate("SPBIMDialogBase", "XXX:"))
        self.comboBox.setItemText(0, _translate("SPBIMDialogBase", "1. XXX"))
        self.comboBox.setItemText(1, _translate("SPBIMDialogBase", "2. XXX"))
        self.comboBox.setItemText(2, _translate("SPBIMDialogBase", "3. XXX"))
        self.comboBox.setItemText(3, _translate("SPBIMDialogBase", "4. XXX"))
        self.comboBox.setItemText(4, _translate("SPBIMDialogBase", "5. XXX"))



if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    SPBIMDialogBase = QtWidgets.QDialog()
    ui = Ui_SPBIMDialogBase()
    ui.setupUi(SPBIMDialogBase)
    SPBIMDialogBase.show()
    sys.exit(app.exec_())

The complete guide to packaging Python GUI applications with PyInstaller.
[[ discount.discount_pc ]]% OFF for the next [[ discount.duration ]] [[discount.description ]] with the code [[ discount.coupon_code ]]

Purchasing Power Parity

Developers in [[ country ]] get [[ discount.discount_pc ]]% OFF on all books & courses with code [[ discount.coupon_code ]]
Well done, you've finished this tutorial! Mark As Complete
[[ user.completed.length ]] completed [[ user.streak+1 ]] day streak

Writie a PyQT5 Plugin in QGIS (Check ComboBox Value) was written by Martin Fitzpatrick .

Martin Fitzpatrick has been developing Python/Qt apps for 8 years. Building desktop applications to make data-analysis tools more user-friendly, Python was the obvious choice. Starting with Tk, later moving to wxWidgets and finally adopting PyQt.