3

I wrote a plugin in PyQGIS, which contains several Ui's (using QT Designer). When I run the code in the QGIS Python console, it works wonderfully. Now I would like to make it available internally for the company as a classic QGIS plugin (start in menu bar). It always worked well with previous plugins, but there was always only one Ui.

At its core there are three important files. 1. __ init __.py, 2. geowerkzeug.py, which is responsible for starting from the menu, and 3. functionality.py, which contains all my functions.

##__init__.py   
 from Plugin.geowerkzeug import GeoWerkzeug
    
    def classFactory(iface):
        plugin = GeoWerkzeug(iface)
        return plugin

Now the geowerkzeug.py:

from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from plugin.functionality import *
from qgis.utils import iface
import os

class GeoWerkzeug:

    def __init__ (self, iface):
        self.iface = iface

    def initGui (self):
        self.startButton = QAction("Plugin starten", self.iface.mainWindow())    
        self.iface.addPluginToMenu('Plugin', self.startButton)
        self.startButton.triggered.connect(self.maskeAufrufen)

    def unload (self):
        self.iface.removePluginMenu('Plugin', self.startButton)

    def maskeAufrufen (self):
        self.gui = MainWindow(self)
        dock_widget = QDockWidget("Plugin", self.iface.mainWindow())
        dock_widget.setWidget(self.gui)
        self.iface.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock_widget)
        dock_widget.setAllowedAreas(QtCore.Qt.RightDockWidgetArea) 
        self.gui.show()

Up to here it works. MainWindow is the first class on functionality.py. The window will appear. But if I click on a button to switch to the next Ui (class), the Ui does not change. I have a total of 17 Ui's in my plugin. Here I only show two classes as an example.

Now the functionality.py:

from PyQt5.uic import loadUi
from PyQt5 import QtWidgets
from PyQt5.QtWidgets import *
from PyQt5 import *
from qgis.core import *
from qgis.utils import iface
from qgis.gui import *
import processing
from PyQt5 import uic
import os

pluginPath = os.path.dirname(__file__)
uiPath = os.path.join(pluginPath, 'mainwindow.ui')
uiPath_second_window = os.path.join(pluginPath, 'window2.ui')

WIDGET, BASE = uic.loadUiType(uiPath)

widget = QDockWidget()

class MainWindow(BASE, WIDGET):
def __init__(self, parent=None):
        super(MainWindow, self).__init__()
        self.gui = loadUi(uiPath, self)
        self.window_second.clicked.connect(self.next_window)

    def next_window(self):
        window_the_second=Second_window()
        widget.setWidget(window_the_second)

class Second_window(BASE, WIDGET):
    def __init__(self):
        super(Second_window, self).__init__()
        self.gui = loadUi(uiPath_second_window , self)

My biggest problem with understanding is how to correctly link my code from functionality.py (which runs in the console) with the other two files. The next problem is that I don't even get an error message that I could build on. The plugin is in the menu bar and it can be started, but after that I can't get any further. I hope my explanations are understandable.

3

I've tested with a minimal plugin.

This one has two UI files :

  • one mainwindow with one pushbutton nammed pb_one
  • one widget with subwidgets

Here the working code :

#!/usr/bin/env python3

import os

from PyQt5 import uic
from PyQt5.QtWidgets import QAction

pluginPath = os.path.dirname(__file__)
path_ui_one = os.path.join(pluginPath, "ui_one.ui")
path_ui_two = os.path.join(pluginPath, "ui_two.ui")

WIDGET_ONE, BASE_ONE = uic.loadUiType(path_ui_one)
WIDGET_TWO, BASE_TWO = uic.loadUiType(path_ui_two)


def classFactory(iface):
    return TwoUiPlugin(iface)


class TwoUiPlugin:
    def __init__(self, iface):
        self.iface = iface

    def initGui(self):
        self.action = QAction('Test Two UI', self.iface.mainWindow())
        self.action.triggered.connect(self.run)
        self.iface.addToolBarIcon(self.action)

    def unload(self):
        self.iface.removeToolBarIcon(self.action)
        del self.action

    def run(self):
        self.main_widget = MyMainWindow()
        self.main_widget.show()


class MyMainWindow(BASE_ONE, WIDGET_ONE):
    def __init__(self, parent=None):
        super(MyMainWindow, self).__init__()
        self.setupUi(self)
        # change here the method
        # self.pb_one.clicked.connect(self.change_central_widget)
        self.pb_one.clicked.connect(self.display_next_window)
        self.second_widget = SecondWidget()

    def change_central_widget(self):
        self.setCentralWidget(self.second_widget)

    def display_next_window(self):
        self.second_widget.show()


class SecondWidget(BASE_TWO, WIDGET_TWO):
    def __init__(self, parent=None):
        super(SecondWidget, self).__init__()
        self.setupUi(self)
5
  • Unfortunately no change. If I just want to run it in the console, these lines are the main key to implementation. But I actually wrote that in geowerkzeug.py. ```widget = QtWidgets.QDockWidget ("Plugin") mainwindow = MainWindow () widget.setWidget (mainwindow) iface.addDockWidget (QtCore.Qt.RightDockWidgetArea, widget) widget.show () Aug 19 '21 at 9:56
  • I will try with two simple different UI. Aug 19 '21 at 10:06
  • 1
    @cc_schr_gis: See my new answer, this one works. Aug 22 '21 at 10:30
  • your code works. Thank you! But now I've used a different suggestion (stackoverflow.com/a/68876010/16298628). The "addDockWidget" is already included in the code. Aug 24 '21 at 8:42
  • In these cases, I advise you to use a QStackedWidget, this is exactly, IMHO, what you need. Aug 24 '21 at 8:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.