2014-02-23 24 views
3

我想在python中创建一个通用类,它将对qlineEdit(或其他控件)中的输入进行一些错误检查,这将弹出一个气球,告诉用户条目无效。喜欢的东西:Qt QlineEdit错误弹出框/气球消息

enter image description here

到目前为止,我已经manged这样的:

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文件: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> 

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

谢谢!

+0

没有足够的代码来重现问题。此代码似乎有时工作不正确取决于布局。你可以发布你用来创建表单的代码(和UI文件,如果有的话),并添加'widgetErrorChecking'它? –

+0

@PavelStrakhov我会尽力重现它。目前的UI文件和代码是巨大的...我试图让这个对话框在布局/小部件结构中非常深入。窗口布局是一个'QVerticalLayout',然后是一个带有'QGridLayout'的'QTabWidget',然后是一个'QFrame'与另一个'QGridLayout'以及'QGridLayout'中的'QLineEdit'。 – Onlyjus

回答

3

QWidget.mapTo方法映射呼叫者到一个祖先插件的坐标系的坐标系内的点

这样的结果:

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

完全等同于:

widget.pos() 

这意味着您可以在在线编辑与底部位置标签:

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

所以,如果你手动迭代所有部件的父母,并总结pos()除了最后一个(窗口位置)我得到正确的坐标参考窗口。

替换:

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

有了:

​​

现在我可以在正确的地方QLabel