0

I am currently trying to create a QGIS plugin with several windows, and it fails.

Here is what I did :

  • With QGIS tool Plugin Builder, I created a plugin my_test
  • This generated a folder with the 3 files : my_test_dialog_base.ui (main plugin window), my_test_dialog.py (loads the plugin ui) and my_test.py (heart of the plugin).
  • my_test_dialog_base.ui is a basic window with a single button. My goal is to open a new window when I click that button.

Interface of my_test_dialog_base.ui : interface of my_test_dialog_base.ui

  • In the plugin folder, I created 2 new files : my_new_window_dialog_base.ui (should be my second window) and my_new_window_dialog.py (loads the second ui)
  • In my_test.py, I added a line to import the my_new_window_dialog.py, and a function openWindow. That function is supposed to call the method MyNewWindow() and open the second window.

At the moment, when I open the plugin in Qgis, the main window is displayed, and when I click on the push button, a log message appaears ("Button clicked"), but that's all. The second window is never opened.

Why doesn't the second window appear, and what I should correct it?

Here are the code --

my_test.py :

from qgis.PyQt.QtCore import QSettings, QTranslator,QCoreApplication
from qgis.PyQt.QtGui import QIcon
from qgis.PyQt.QtWidgets import QAction
from qgis.core import Qgis
from .resources import *
from .my_test_dialog import MyTestDialog
from .my_new_window_dialog import MyNewWindow
import os.path


class MyTest:

def __init__(self, iface):
    # 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',
        'MyTest_{}.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'&My Test')

    # 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

def tr(self, message):
    return QCoreApplication.translate('MyTest', 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):

    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):
    icon_path = ':/plugins/my_test/icon.png'
    self.add_action(
        icon_path,
        text=self.tr(u'Make a test'),
        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."""
    for action in self.actions:
        self.iface.removePluginMenu(
            self.tr(u'&My Test'),
            action)
        self.iface.removeToolBarIcon(action)

def openWindow(self):
    self.iface.messageBar().pushMessage("Button clicked.", level=Qgis.Success, duration=5)
    self.nw = MyNewWindow()
    self.nw.show


def run(self):
    if self.first_start == True:
        self.first_start = False
        self.dlg = MyTestDialog()  
        self.dlg.pushButton.clicked.connect(self.openWindow) 

    # 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

my_test_dialog.py :

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

FORM_CLASS, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'my_test_dialog_base.ui'))

class MyTestDialog(QtWidgets.QDialog, FORM_CLASS):
    def __init__(self, parent=None):
        super(MyTestDialog, self).__init__(parent)
        self.setupUi(self)

my_new_window_dialog.py :

import os
from PyQt5 import QtCore
from qgis.PyQt import uic
from PyQt5 import QtWidgets

FORM_CLASS, _ = uic.loadUiType(os.path.join(os.path.dirname(__file__), 'my_new_window_dialog_base.ui'))


class MyNewWindow(QtWidgets.QDialog, FORM_CLASS):
    def __init__(self,parent=None):
        super(MyNewWindow, self).__init__(parent)
        self.setupUi(self)
2
  • 1
    Add parenthesis to self.nw.show -> self.nw.show(). This is why it does not work. Mar 13 at 10:10
  • it works ! Yeaaah ! Thank you very much Mar 13 at 10:28

1 Answer 1

1

It was in fact a basic error, I forgot the breaks after the 'show' function...

Just in case it would help, when using show() I can still interact with the main window. However, if I use exec_(), the main window is frozen, and then I can only use the second window.

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