Qt QlineEdit错误弹出/气球消息

时间:2014-02-23 04:03:48

标签: python qt pyqt pyqt4 pyside

我正在尝试在python中创建一个泛型类,它将对qlineEdit(或其他小部件)中的输入进行一些错误检查,这将弹出一个气球告诉用户该条目无效。类似的东西:

enter image description here

到目前为止,我已经对此进行了管理:

enter image description here

我真正的问题是: 如何获取qlineEdit小部件的正确坐标以将气球放置在正确的位置?以下代码应放在QlineEdit的左下角?它位于底部,但不是左侧。


当前代码:

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>

关于如何做得更好的任何其他想法?

谢谢!

2 个答案:

答案 0 :(得分:3)

QWidget.mapTo方法将调用者的坐标系内的点映射到祖先小部件的坐标系。

结果:

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

完全等同于:

    widget.pos()

这意味着您可以使用以下符号将标签放置在行编辑的底部:

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

答案 1 :(得分:1)

因此,如果您手动遍历所有窗口小部件的父窗口,并总结pos()除了最后一个窗口位置(窗口位置),我将获得参考窗口的正确坐标。

替换:

widgetPos = self.widget.mapTo(self.parent(), self.widget.pos())

使用:

w = self.widget
x = []
y = []
while w:
    x.append(w.pos().x())
    y.append(w.pos().y())
    w = w.parent()

widgetPos = QtCore.QPoint(sum(x[:-1]), sum(y[:-1]))

现在我可以将QLabel放在正确的位置!