5

I am trying to write a plugin with a input control such as textbox on it. I looked around quite a bit for building plugins. But I can only find examples of how to build a plugin with buttons/icons in its toolbar.

How can I add other widgets such as a textbox on my plugin's toolbar?

For the button, there isn't much to handle except for a callback when it's clicked. I imagine it would be quite different for a textbox as one needs to associate the input control to e.g. a global variable??

For now, I need interaction with the textbox (QLineEdit). I want to implement a plugin for going to the next feature where I can display the row number of the current record, and jump to any given row by entering its row number.

I am using QGIS2.99 and Qt5, the standard Plugin Builder and pb_tool to create and deploy the plugin template. I suppose I need to add the QLineEdit in initGui() of the main py file(as shown below). I don't know much about Qt5, and only figured I might need addUserInputWidget() and/or connect it with the add_action() function? But I don't know how to put the pieces together, and register the events etc.

Here is what I have so far:

def initGui(self):
    """Create the menu entries and toolbar icons inside the QGIS GUI."""

    # Create & add a textbox
    self.textbox = QLineEdit(self.iface.mainWindow())
    self.textbox.resize(80,20)

    self.txtAction = self.toolbar.addWidget(self.textbox)
    #should I use addUserInputWidget(self.textbox) #??

    self.txtAction.setToolTip(self.tr(u'Current Row Number'))
    #callback=self.runTextChange   how to register an event handler?

The UI shows but there is no interaction.

Can someone help explain how to link the QLineEdit to the toolbar so that I can get/change the text value?

Also, a minor issue I can't figure out is that the textbox takes up the full width of the toolbar no matter what I use in its .resize() method. How should I limit its width?

  • Have a look at my answer. I'm not sure it can help you so, if you think it is very far from your needs or simply off-topic, please notify me it and I will delete the answer. – mgri Jun 20 '17 at 8:24
5

Nice answer by @mgri (don't delete it as it is useful to use within QGIS!). I tested the following on QGIS 2.18 also with Qt4 but perhaps it might be useful too as the other answer. A couple of things to note:

  • You can use self.textbox.setFixedWidth(80) to set the width of the textbox.
  • You can use self.textbox.textChanged.connect(self.runTextChange) to connect the textbox to a function whenever the text is changed.

Here is the code used:

def initGui(self):
    """Create the menu entries and toolbar icons inside the QGIS GUI."""
    # Create & add a textbox
    self.textbox = QLineEdit(self.iface.mainWindow())
    # Set width
    self.textbox.setFixedWidth(80)
    # Add textbox to toolbar
    self.txtAction = self.toolbar.addWidget(self.textbox)
    # Set tooltip
    self.txtAction.setToolTip(self.tr(u'Current Row Number'))
    # Set callback
    self.textbox.textChanged.connect(self.runTextChange)


def runTextChange(self, rownum):
    # Set active layer
    layer = iface.activeLayer()
    # If textbox is empty or 0 then deselect all features
    if rownum == '' or int(rownum) == 0:
        layer.deselect([feat.id() for feat in layer.getFeatures()])
    else:
        # Else select row number matching the entered value
        for feat in layer.getFeatures():
            if feat.id() == int(rownum) - 1:
                layer.setSelectedFeatures([feat.id()])

Example:

Example

  • 1
    Quite different from my answer, but I'm sure this will solve the issue :) – mgri Jun 20 '17 at 10:24
  • 1
    @mgri - Haven't used QGIS 2.99 or Qt5 so who knows :) Although I am dreading how much changes I will need to make to my plugins when QGIS 3 is officially released >_< – Joseph Jun 20 '17 at 10:26
  • 1
    I know, it will be a common nightmare for all of us (and probably for the whole community since there will be a lot of answers with deprecated APIs). – mgri Jun 20 '17 at 10:33
  • 1
    Thanks! I only needed to change the last line to layer.selectByIds(... to make it work.. – tinlyx Jun 20 '17 at 15:03
4

This would be more a comment than an answer (and most probably a starting point rather than a solution), but I post it here since there is some code.

If you want to set up a basic textbox, you may use this code:

from PyQt4.QtGui import *

input_dialog = QInputDialog()
title = "Dialog Title"
label = "Enter some text here: "
enum_type = QLineEdit.Normal
default_text = "<your text here>"

res = QInputDialog.getText(input_dialog, title, label, enum_type, default_text)

The res variable is a tuple that stores your text (as a string) and a boolean which is used to verify that an input was typed. You can also change the last line in:

text_var, typed = QInputDialog.getText(input_dialog, title, label, enum_type, default_text)

for directly having your text stored in the text_var variable.

Note that this works for Qt4, but I think it should follow the same syntax also for Qt5.

  • Thanks a lot. I really appreciate your help. But I am looking for a more direct connection between the lineedit and the python code/global variable so that they notify each other of value changes and act accordingly. – tinlyx Jun 20 '17 at 9:55
  • @tinlyx You confirmed my doubts about the usefulness of my tip. Sorry, but these operations are not my cup of tea... Good luck! :) – mgri Jun 20 '17 at 9:57

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.