13

I have built a plugin for feeding a Spatialite database with an input mask. There are two fields which represent the min/max dimension of an object.

In the moment I call the Measure Tool (iface.actionMeasure().trigger()) with the two Push Buttons "measure", click the dimension and type the value with my keyboard into the fields (QLineEdit).

Is there the possibility that after I do the right click (finish measuring) with the Measure Tool the value will be automatically committed to the field (min or max, QLineEdit)?

  1. Call Measure Tool (it works)
  2. Left Click: begin measuring
  3. and 4. at once: Right click and commit Total value of Measure Tool to the min field (QLineEdit).

enter image description here

UPDATE 1:

One day after asking this question I've got the idea to have a linestring layer which I could use as a measure tool (ST_Length(geom)). The advantage is that you could have the full control of manipulating and obtaining data from it. A disadvantage is a additional layer in the project.

A workflow could be:

  1. click measure: toggle editing, activate "Add Feature"

  2. Create linestring that represents the min dimension of an object

  3. Confirm changes, calculate length of linestring (ST_Length(geom)), commit length to QLineEdit

  4. Close Dialog and remove linestring (DELETE FROM )

But my actual question remains. Is there a way to get the distance value from the Measure Tool directly?

Update 2:

With the help if Jakob I can update my QLineEdit with the Total value of the Measure Tool until I close the Measure Tool. Then the value is set to '0,000 m'. I solved this problem by using this:

def text_changed(str_measure):
    if str_measure == '0,000 m':
        pass
    else:
        self.min.setText(str_measure)

It works, but I don't know if this is a proper solution.

10
+100
  1. Find the QgsMeasureBase widget
  2. Find the QLineEdit with the total value in the widget
  3. Connect a slot to the QLineEdit textChanged signal.

This code should get you going:

def text_changed(str_measure):
        QgsMessageLog.logMessage(str_measure, "test")

from qgis.core import QgsMessageLog
from PyQt4.QtGui import QApplication, QLineEdit
from PyQt4.QtCore import pyqtSignal

QgsMessageLog.logMessage("start", "test")

for w in QApplication.instance().allWidgets():
    name = w.objectName()
    if name == 'QgsMeasureBase':
        QgsMessageLog.logMessage(name, "test")

        lineedit = w.findChild(QLineEdit, 'editTotal')
        QgsMessageLog.logMessage('Text: {}'.format(lineedit.text()),'test')

        #{object}.{signal}.connect({slot})
        lineedit.textChanged.connect(text_changed) 
        break

QgsMessageLog.logMessage("stop", "test")
QgsMessageLog.logMessage("", "test")

For demo the measured values are written to the Log Message Panel in a tab called test. Instead you update you min and max QLineEdit.

enter image description here

Actually the code can be shortened. The for loop above was because I did not know of the name of the QgsMeasureBase widget, and had to take a look at all the widgets for the text 'measure'.

def text_changed(str_measure):
    QgsMessageLog.logMessage(str_measure, "test")

from qgis.core import QgsMessageLog
from PyQt4.QtGui import QApplication, QLineEdit
from PyQt4.QtCore import pyqtSignal

QgsMessageLog.logMessage("---start---", "test")

widget_measure = [w for w in QApplication.instance().allWidgets() if w.objectName() == 'QgsMeasureBase'][0]
lineedit = widget_measure.findChild(QLineEdit, 'editTotal')
lineedit.textChanged.connect(text_changed) 

QgsMessageLog.logMessage('Text: {}'.format(lineedit.text()),'test')

QgsMessageLog.logMessage("---stop---", "test")
  • 1
    Nice Answer, I am not a programmer but I understand this logic. Well done. – Mapperz May 3 '17 at 15:10
  • I'm able to connect the 'editTotal' value to my QLineEdit, successfully. But when I close the QgsMeasureBase dialog the value (QLineEdit) is set to 0. How can I avoid this when I close the dialog? – Stefan May 4 '17 at 6:34
  • When I print all the children of the QgsMeasureBase dialog with: widget_measure = [w for w in QApplication.instance().allWidgets() if w.objectName() == 'QgsMeasureBase'][0] then for i in widget_measure.children(): print i.objectName(), there is the widget 'buttonBox', which I hope encludes the button QDialogButtonBox.Close. Can this be used to say "if close is clicked keep editTotal value or do nothing"? – Stefan May 4 '17 at 7:07
  • The problem is the textchanged signal is called before reject signal. You can test it by adding: buttonbox = widget_measure.findChild(QDialogButtonBox, 'buttonBox') buttonbox.rejected.connect(buttonbox_rejected) with the function in top: def buttonbox_rejected(): QgsMessageLog.logMessage('rejected', "test") – Jakob May 4 '17 at 12:13
  • Can you store the measure length in text_changed slot in an array and then on the reject slot pick the second last entered value in the array for you gui. – Jakob May 4 '17 at 12:16

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.