Qt QlineEdit error popup/balloon message

pyqt, pyqt4, pyside, python, qt

Solution

The QWidget.mapTo method maps a point within the co-ordinate system of the caller to the co-ordinate system of an ancestor widget.

So the result of:

    widget.mapTo(widget.parentWidget(), QPoint(0, 0))

is exactly equivalent to:

    widget.pos()

This means you can position the label at the bottom of the line-edit with:

    self.move(self.widget.mapTo(
        self.parentWidget(), self.widget.rect().bottomLeft()))

Problem

I am trying to create a generic class in python that will do some error checking of the input in a qlineEdit (or other widget for that matter) that will popup a balloon telling the user that the entry is invalid. Something like: So far I have manged this: My real question is: How do I get the correct coordinates of the qlineEdit widget to place the balloon in the correct position? The following code should be placing it at the bottom left corner of the QlineEdit? It is at the bottom but not the left hand side. Current Code: ``` import sys from PyQt4 import QtGui, QtCore, uic class widgetErrorChecking(QtGui.QLabel): def __init__(self, parent, widget, app): QtGui.QLabel.__init__(self, parent) self.widget = widget self.hide() effect = QtGui.QGraphicsDropShadowEffect() effect.setBlurRadius(10) effect.setOffset(2,2) self.setGraphicsEffect(effect) self.setStyleSheet('''QLabel { background-color:red; border: darkRed; border-radius: 5px; } ''') if isinstance(widget, QtGui.QLineEdit): widget.textEdited.connect(self.checkWidgetValue) app.focusChanged.connect(self.hide) def checkWidgetValue(self, value): if not value: return try: value = float(value) except ValueError: value = 0.0 if 0.0 >value: self.showMessage('Needs to be greater then 0.0') elif value>100: self.showMessage('Needs to be less then 100.0') else: self.hide() def showMessage(self, message = None): ''' Show the widget. ''' self.setText(message) self.adjustSize() self.update() self.show() labelGeo = self.geometry() # vvvv whats wrong with this vvvv widgetPos = self.widget.mapTo(self.parent(), self.widget.pos()) widgetGeo = self.widget.geometry() newPos = QtCore.QPoint(widgetPos.x(), widgetPos.y()+widgetGeo.height()) self.move(newPos) class mainWindow(QtGui.QMainWindow): ''' Main window class handeling all gui interactions ''' def __init__(self, app): QtGui.QMainWindow.__init__(self) self.app = app self.ui = uic.loadUi('testErrorMessage.ui', self) # Add error checking errorChecker1 = widgetErrorChecking(self, self.ui.lineEdit1, self.app) errorChecker2 = widgetErrorChecking(self, self.ui.lineEdit2, self.app) errorChecker3 = widgetErrorChecking(self, self.ui.lineEdit3, self.app) if __name__ == "__main__": app = QtGui.QApplication(sys.argv) gui = mainWindow(app) gui.show() app.exec_() app.deleteLater() sys.exit() ``` ui file: testErrorMessage.ui ``` <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>493</width> <height>348</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"> <layout class="QVBoxLayout" name="verticalLayout"> <item> <widget class="QGroupBox" name="groupBox"> <property name="title"> <string>groupBox1</string> </property> <layout class="QGridLayout" name="gridLayout"> <item row="0" column="0"> <widget class="QGroupBox" name="groupBox_4"> <property name="title"> <string>groupBoxA</string> </property> <layout class="QHBoxLayout" name="horizontalLayout_2"> <item> <widget class="QLabel" name="label_2"> <property name="text"> <string>LineEdit1</string> </property> </widget> </item> <item> <widget class="QLineEdit" name="lineEdit1"/> </item> </layout> </widget> </item> <item row="0" column="1"> <widget class="QGroupBox" name="groupBox_3"> <property name="title"> <string>groupBoxB</string> </property> <layout class="QGridLayout" name="gridLayout_2"> <item row="0" column="0"> <widget class="QLabel" name="label"> <property name="text"> <string>LineEdit2</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QLineEdit" name="lineEdit2"/> </item> </layout> </widget> </item> </layout> </widget> </item> <item> <widget class="QGroupBox" name="groupBox_2"> <property name="title"> <string>groupBox2</string> </property> <layout class="QHBoxLayout" name="horizontalLayout"> <item> <widget class="QLabel" name="label_3"> <property name="text"> <string>LineEdit3</string> </property> </widget> </item> <item> <widget class="QLineEdit" name="lineEdit3"/> </item> </layout> </widget> </item> </layout> </widget> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>493</width> <height>21</height> </rect> </property> <widget class="QMenu" name="menuFile"> <property name="title"> <string>File</string> </property> <addaction name="actionClose"/> </widget> <addaction name="menuFile"/> </widget> <widget class="QStatusBar" name="statusbar"/> <action name="actionClose"> <property name="text"> <string>Close</string> </property> </action> </widget> <resources/> <connections> <connection> <sender>actionClose</sender> <signal>triggered()</signal> <receiver>MainWindow</receiver> <slot>close()</slot> <hints> <hint type="sourcelabel"> <x>-1</x> <y>-1</y> </hint> <hint type="destinationlabel"> <x>399</x> <y>299</y> </hint> </hints> </connection> </connections> </ui> ``` Any other ideas on how to do this better? Thanks!

Original source