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.
The main issue which causes the second window not to appear, is that you never show the QDockWidget
. With widget.setWidget(window_the_second)
you set the content, but it doesn't make the window appear.
In your method that shows the first window, add the dockwidget with self.iface.addDockWidget(QtCore.Qt.RightDockWidgetArea, widget)
then set your first window as content of that dockwidget (widget.setWidget(self.gui)
).
In general, you got some things a bit mixed up, so I'll try to clarify two points.
uic.loadUiType
. In order to have a second window display your second ui, you can't sublass the same BASE
and WIDGET
. Call uic.loadUiType
for each of your UI-Files instead.setupUi()
to initialize the UI. Then you can also get rid of any loadUi
.Implementing my advices then results in the following:
WIDGET, BASE = uic.loadUiType('1.ui')
WIDGET2, BASE2 = uic.loadUiType('2.ui')
widget = QDockWidget()
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):
# add DockWidget to GUI
self.iface.addDockWidget(QtCore.Qt.RightDockWidgetArea, widget)
widget.setAllowedAreas(QtCore.Qt.RightDockWidgetArea)
# set first window as content of the DockWidget
self.gui = MainWindow(self)
widget.setWidget(self.gui)
class MainWindow(BASE, WIDGET):
def __init__(self, parent=None):
super(MainWindow, self).__init__()
self.setupUi(self)
self.window_second.clicked.connect(self.next_window)
def next_window(self):
# set second window as content of the DockWidget
window_the_second=Second_window()
widget.setWidget(window_the_second)
class Second_window(BASE2, WIDGET2):
def __init__(self):
super(Second_window, self).__init__()
self.setupUi(self)