Qt QlineEdit错误弹出/气泡消息

3
我正在尝试在Python中创建一个通用类,对qlineEdit(或其他窗口小部件)的输入进行一些错误检查,并弹出气球告诉用户该条目无效。例如:
``` so far I have manged this ```
我的真正问题是:如何获取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()

用户界面文件: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>

还有其他更好的方法吗?

谢谢!


没有足够的代码来重现问题。这段代码似乎有时会根据布局工作不正确。您能否发布用于创建表单并添加widgetErrorChecking的代码(以及UI文件,如果有)? - Pavel Strakhov
@PavelStrakhov 我会尝试重现它。当前的UI文件和代码非常庞大...我正在尝试制作的小部件在布局/小部件结构中非常深。窗口布局是QVerticalLayout,然后是带有QGridLayoutQTabWidget,然后是另一个带有前一个QGridLayout中的QLineEditQFrame - Onlyjus
2个回答

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())

With:

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放到正确的位置了!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接