2

I need your help I am developing a dialog box (which I will call toolraster) in QGis to interact with raster layers. I want it to display when I click on a menu I insert in the QGis interface.

I created Toolraster as a class that extends QtWidgets, a QWidget. Create the QAction and connect it to the toolraster instance function. Create the submenu with iface.pluginMenu().addSeparator() and iface.pluginMenu().addAction(activar). Example below.

The problem: when I run the menu the dialog box opens and closes instantly. It doesn't report any errors

When I perform the same procedure with a QInputDialog or a QMessageBox it doesn't present any problems.

But with a class like this it is a problem:

from qgis import PyQt
from qgis.PyQt import QtWidgets

class test(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("clase de prueba")
        layout = QVBoxLayout()
        widgets = [QCheckBox,
            QComboBox,
            QDateEdit,
            QDateTimeEdit,
            QDial,
            QDoubleSpinBox]
        for w in widgets:
            layout.addWidget(w())
            
        self.setLayout(layout)

def activar():
    h=test()
    h.show()

test_action=QAction("Menu de prueba")
test_action.triggered.connect(activar)
iface.pluginMenu().addSeparator()
iface.pluginMenu().addAction(test_action)

Note: when I execute the function activar() in the console the same thing happens, if I insert the show() inside the class too

  • Greetings, I found a solution (or so I hope) instead of working on a QWidget I use a QDialog. Then the function that triggers the event when you click on the menu instead of the show method uses .exec_() In the first test it runs without problem. I look forward to your comments – Luis Perez Jun 18 at 20:31
4

You should move the h = test() outside of activar function (tested and it works). While doing this, you will also avoid creating as many widgets as you push on the button and instead create one widget and show/hide it.

from qgis import PyQt
from qgis.PyQt import QtWidgets

class test(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("clase de prueba")
        layout = QVBoxLayout()
        widgets = [QCheckBox,
            QComboBox,
            QDateEdit,
            QDateTimeEdit,
            QDial,
            QDoubleSpinBox]
        for w in widgets:
            layout.addWidget(w())
            
        self.setLayout(layout)

h=test()


def activar():
    h.show()

test_action=QAction("Menu de prueba")
test_action.triggered.connect(activar)
iface.pluginMenu().addSeparator()
iface.pluginMenu().addAction(test_action)
| improve this answer | |
  • Thanks Thomas, that works. Could you explain to me why the error occurs? – Luis Perez Jun 18 at 22:22
  • Would lie to say I know exactly why... Sometimes, you guess issues are related to something but do not have a proper explanation. Just need to accept it :) – ThomasG77 Jun 18 at 22:30
  • 2
    @Luis Perez, I think the issue comes down to scope. Since you instantiate the test class object inside your activar() method, it goes out of scope as soon as the function returns. IMHO ThomasG77's answer to only create the test class instance once, outside the function is definitely the correct approach. However, purely for illustrative purposes- in your original example, if you add the line global h above h = test() inside the activar() method, it will also work. – Ben W Jun 18 at 23:50
  • 1
    Thank you, Ben. It works. First time I use global, I'm learning and developing :). I guess global is to expand the scope of the variable. This clarifies the cause of the error – Luis Perez Jun 19 at 0:07

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.