kopi,
QMessageBox, and similar convenience classes, allow for quick creation of standard dialogs, generally using static methods within their class. Creating custom buttons and Qt widgets requires making the Qt signal/slot connections between them, as per the desired GUI interaction for the purpose.
When using QtDesigner and after the compilation of your form to a ui.py file, you will want to import it into a Python module and instantiate it, so that you can directly reference the form's widgets. With PyQGIS plugins, this is usually done in a module specific to the dialog, though with very simple plugins it can be done inside the plugin's base class.
A very good reference for creating PyQGIS plugins, in addition to the PyQGIS Cookbook, is the QGIS Workshop v1.0.0: for help with your question, specifically the section on integrating a tool's output with the GUI:
01 from PyQt4 import QtCore, QtGui
02 from ui_vector_selectbypoint import Ui_vector_selectbypoint
03
04 class vector_selectbypointDialog(QtGui.QDialog):
05
06 def __init__(self):
07 QtGui.QDialog.__init__(self)
08 # Set up the user interface from Designer.
09 self.ui = Ui_vector_selectbypoint()
10 self.ui.setupUi(self)
Line by line:
01 Basic PyQt4 imports.
02 Import of custom form's class from its compiled ui file.
04 Your custom dialog's class, which inherits from QDialog.
06 init method called when your dialog is instantiated.
07 Instantiate parent QDialog class, so your class gains its attributes.
09 Instantiate and assign your QtDesigner form class.
10 Call the form class's setupUi() method, so its widgets are available.
Once you have self.ui
referencing your custom layout form, you can access its widgets anywhere in your custom dialog class and set up signal/slot connections or named slots.
Example showing new style signal/slot connection (using some object names from comments) and named slot connection:
from PyQt4 import QtCore, QtGui
from ui_ubsearch import Ui_UBSearchDialog # don't know name of your form class
class UBSearchDialog(QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self)
# Set up the user interface from Designer.
self.ui = Ui_UBSearchDialog()
self.ui.setupUi(self)
# make new style signal/slot connection
self.ui.bgrz.clicked.connect(self.exec_grz)
# slot for connection
def exec_grz(self):
# do something
pass # <-- replace with actual code
# named slot example
# (doesn't require a previously built connection for form widgets)
@QtCore.pyqtSlot()
def on_myOtherFormButton_clicked(self):
# do something
pass # <-- replace with actual code
Your UBSearchDialog
class will, in turn, need to be instantiated elsewhere (e.g. imported into your plugin's base class and instantiated in its run() method):
ubs_dlg = UBSearchDialog()
ubs_dlg.exec_()
Also, see https://stackoverflow.com/questions/2462401 for more examples concerning named slots and how new style connections keep things cleaner and more 'Pythonic.'
Concerning your second question, there are a couple of things you'll want to clean up before testing more. First, you have multiple imports for the same modules. Your custom dialog module could look like this instead ...
from PyQt4.QtCore import pyqtSlot
from PyQt4.QtGui import QDialog
import datavisualization
from ui_ubsearch import Ui_ubsearch
class ubsearchDialog(QDialog):
def __init__(self, iface):
QDialog.__init__(self)
# Set up the user interface from Designer.
self.ui = Ui_ubsearch()
self.ui.setupUi(self)
# Save reference to the QGIS interface
self.iface = iface
@pyqtSlot()
def on_bgrz_clicked(self):
# Get an instance of the class
d = datavisualization.datavisualization(self.iface)
# Call the method of the intance
d.data_visualization()
# Close UI
self.close()
Of note here is the import of only those names from the PyQt4 modules that are used in the script (QDialog and pyqtSlot). See working with Python modules, for more info. All other unused module imports were removed. You can use pylint to help with finding those unused modules.
Also, when constructing an instance of the class the iface reference is gathered and assigned so it can be passed to your datavisualization module (fixing the parameter error). This means you have to pass iface in from your original plugin module that calls the construction of the custom dialog, e.g. ubsearchDialog(self.iface)
. So, iface needs a saved reference in your base plugin module as well, in order to be passed to your dialog. This is usually already set up for you if you use tools like Plugin Builder.
You will want to clean up your datavisualization module's imports in a similar fashion.
import os
import datetime
import time
import psycopg2
from PyQt4.QtGui import QMessageBox
from qgis import core
Lastly, you will want to read up on PEP8, Python style guide. Your pasted code contained a mix of spaces and tabs for indention: only-spaces is generally preferred.
Here is my example code. To use the code I prepared a QDialog
in QtDesigner with a simple QLineEdit
named "field" and a QPushButton
named "push" - In the form_open()
function you have to find these components. Afterwards, clicked signal of the button is connected to function. Try to enter your code in function check_and_set_field_value()
:
from PyQt4.QtGui import QLineEdit, QPushButton
form = None
field = None
def form_open(my_dialog, layer_id, feature_id):
global form
global field
form = my_dialog
field = form.findChild(QLineEdit, "field")
push = form.findChild(QPushButton, "push")
push.clicked.connect(check_and_set_field_value)
def check_and_set_field_value():
# Your code goes here...
# Example return value:
return_value = 'test'
if return_value is not None:
field.setText(return_value)
Best Answer
When you create action for button add:
In action callback, when you set your tool as active, toggle button on:
Add tool deactivation callback, which toggle button off:
And connect it somewhere in init code: