Pyqt5 调整大小时更新子位置 parent

Pyqt5 Update childs position when resize parent

在 Python 和 PyQt5 中,我创建了一个 QmainWindow 作为 parent 和一个 Qwidget 作为 child。 一切正常,但当我调整 window 大小时,child 始终保持在同一位置。 我需要一个 child 的解决方案,当我调整 parent 小部件的大小时,该位置将更新。

在 parent 小部件中我有一个 message-bubble。 child 小部件只是一个徽章,其中显示新消息的数量。如果我调整 window 的大小,message-bubble 正在移动,但徽章保持在同一位置,徽章远离消息气泡。

代码如下:

from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget
from UIs.badge import Ui_Form
from PyQt5.QtCore import  Qt
from UIs.message import Ui_MainWindow

import sys

"""
    This is my Badge class. 
    It is just one QLabel with 'FontAwesome Solid' Font to get a Dot (circle)
    and another QLabel for the number.
    Without any layout for free positioning (Label over label)
"""
class badge(QWidget):
    def __init__(self,parent=None):
        super(badge, self).__init__(parent)
        self.ui = Ui_Form()
        self.ui.setupUi(self)
        self.ui.label.setProperty("text","0")
        self.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents)
        
"""
    This is my MainWindow class. 
    With Flat QPushButton and 'FontAwesome' as well to get the Bubble (comments)  
"""  
class mainW(QMainWindow):
    def __init__(self):
        super(mainW, self).__init__()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)   
        self.label_badge = badge(self.ui.btn_comments)
        self.label_badge.setGeometry(QtCore.QRect(self.ui.btn_comments.x(),self.ui.btn_comments.y(),self.label_badge.width(),self.label_badge.height()))
   

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = mainW()
    window.show()
    app.exec()

所以,当我启动应用程序时,一切看起来都很正常,但是当我调整 window 大小时,袋子始终停留在相同位置,但应该停留在气泡旁边。

我读了一些关于 eventFilters 的内容,但我不明白其中的机制。

上面的代码只是我写的代码。如果您需要由 qt 设计器生成的代码,请告诉我。

这是用qt creator制作的徽章:

这是启动应用后的window

当我调整大小时它看起来像这样

下次尝试:

问题总是一样的。 我现在已经删除了所有不需要的东西,只留下了气泡的部分。

test_bubble.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>450</width>
    <height>370</height>
   </rect>
  </property>
  <property name="minimumSize">
   <size>
    <width>450</width>
    <height>370</height>
   </size>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <property name="styleSheet">
   <string notr="true"/>
  </property>
  <widget class="QWidget" name="centralwidget">
   <property name="styleSheet">
    <string notr="true">QWidget#centralwidget{
    background-color: rgb(54, 54, 54);
}</string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout_2">
    <property name="spacing">
     <number>0</number>
    </property>
    <property name="leftMargin">
     <number>0</number>
    </property>
    <property name="topMargin">
     <number>0</number>
    </property>
    <property name="rightMargin">
     <number>0</number>
    </property>
    <property name="bottomMargin">
     <number>0</number>
    </property>
    <item>
     <widget class="QFrame" name="frame">
      <property name="styleSheet">
       <string notr="true">QFrame{
    border: 0px solid rgb(255, 255, 255)
}</string>
      </property>
      <property name="frameShape">
       <enum>QFrame::StyledPanel</enum>
      </property>
      <property name="frameShadow">
       <enum>QFrame::Raised</enum>
      </property>
      <layout class="QVBoxLayout" name="verticalLayout" stretch="0">
       <item alignment="Qt::AlignLeft">
        <widget class="QFrame" name="frame_7">
         <property name="sizePolicy">
          <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
         <property name="frameShape">
          <enum>QFrame::StyledPanel</enum>
         </property>
         <property name="frameShadow">
          <enum>QFrame::Raised</enum>
         </property>
         <layout class="QVBoxLayout" name="verticalLayout_8">
          <property name="spacing">
           <number>0</number>
          </property>
          <property name="leftMargin">
           <number>0</number>
          </property>
          <property name="topMargin">
           <number>0</number>
          </property>
          <property name="rightMargin">
           <number>0</number>
          </property>
          <property name="bottomMargin">
           <number>0</number>
          </property>
          <item alignment="Qt::AlignLeft">
           <widget class="QPushButton" name="btn_comments">
            <property name="sizePolicy">
             <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
              <horstretch>0</horstretch>
              <verstretch>0</verstretch>
             </sizepolicy>
            </property>
            <property name="font">
             <font>
              <family>Font Awesome 5 Free Solid</family>
              <pointsize>29</pointsize>
              <kerning>true</kerning>
             </font>
            </property>
            <property name="cursor">
             <cursorShape>PointingHandCursor</cursorShape>
            </property>
            <property name="styleSheet">
             <string notr="true">QPushButton{
    color: rgb(28, 130, 255);
    background-color:none;
    border:none;
    outline:0;
    margin:0;
    padding:0;
}

QPushButton:hover{
    color: rgb(30, 148, 232);
}</string>
            </property>
            <property name="text">
             <string>comments</string>
            </property>
            <property name="flat">
             <bool>true</bool>
            </property>
           </widget>
          </item>
         </layout>
        </widget>
       </item>
      </layout>
     </widget>
    </item>
   </layout>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

badge.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>94</width>
    <height>20</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <widget class="QLabel" name="label_2">
   <property name="geometry">
    <rect>
     <x>3</x>
     <y>0</y>
     <width>20</width>
     <height>20</height>
    </rect>
   </property>
   <property name="font">
    <font>
     <family>Font Awesome 5 Free Solid</family>
     <pointsize>12</pointsize>
     <weight>75</weight>
     <bold>true</bold>
    </font>
   </property>
   <property name="styleSheet">
    <string notr="true">QLabel#label_2{
    border-radius: 5px;
    color:rgb(170, 0, 0);
}</string>
   </property>
   <property name="text">
    <string>circle</string>
   </property>
   <property name="alignment">
    <set>Qt::AlignCenter</set>
   </property>
  </widget>
  <widget class="QLabel" name="label">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>0</y>
     <width>21</width>
     <height>21</height>
    </rect>
   </property>
   <property name="font">
    <font>
     <family>Arial</family>
     <pointsize>7</pointsize>
     <weight>75</weight>
     <bold>true</bold>
    </font>
   </property>
   <property name="styleSheet">
    <string notr="true">QLabel#label{
    color:rgb(255, 255, 255)
}</string>
   </property>
   <property name="text">
    <string>8</string>
   </property>
  </widget>
 </widget>
 <resources/>
 <connections/>
</ui>

顺便说一句。 删除不需要的部分后,我没有编辑上面的代码。 那样可以么? 如果您需要其他东西,请告诉我。

我经常想知道处理重叠小部件的首选方法是什么。我能想到的最简单的方法是将所有重叠元素放入单个容器中,例如 QWidget 或 QFrame。我在 Designer 中做了布局,使用 QWidget 作为容器:

overlap1.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>262</width>
    <height>344</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QLabel" name="label_2">
      <property name="text">
       <string>Logged in:</string>
      </property>
     </widget>
    </item>
    <item>
     <layout class="QHBoxLayout" name="horizontalLayout">
      <item>
       <widget class="QWidget" name="widget" native="true">
        <property name="minimumSize">
         <size>
          <width>52</width>
          <height>32</height>
         </size>
        </property>
        <widget class="QLabel" name="lblNumMsg">
         <property name="geometry">
          <rect>
           <x>8</x>
           <y>2</y>
           <width>16</width>
           <height>16</height>
          </rect>
         </property>
         <property name="minimumSize">
          <size>
           <width>5</width>
           <height>5</height>
          </size>
         </property>
         <property name="text">
          <string>0</string>
         </property>
        </widget>
        <widget class="QLabel" name="lblBubble">
         <property name="geometry">
          <rect>
           <x>1</x>
           <y>1</y>
           <width>51</width>
           <height>31</height>
          </rect>
         </property>
         <property name="sizePolicy">
          <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
           <horstretch>0</horstretch>
           <verstretch>0</verstretch>
          </sizepolicy>
         </property>
         <property name="minimumSize">
          <size>
           <width>51</width>
           <height>31</height>
          </size>
         </property>
         <property name="text">
          <string/>
         </property>
         <property name="pixmap">
          <pixmap>bubble.png</pixmap>
         </property>
         <property name="scaledContents">
          <bool>true</bool>
         </property>
        </widget>
        <widget class="QLabel" name="lblCircle">
         <property name="geometry">
          <rect>
           <x>5</x>
           <y>0</y>
           <width>16</width>
           <height>21</height>
          </rect>
         </property>
         <property name="text">
          <string/>
         </property>
         <property name="pixmap">
          <pixmap>red_circle.png</pixmap>
         </property>
         <property name="scaledContents">
          <bool>true</bool>
         </property>
        </widget>
        <zorder>lblBubble</zorder>
        <zorder>lblCircle</zorder>
        <zorder>lblNumMsg</zorder>
       </widget>
      </item>
      <item>
       <spacer name="horizontalSpacer">
        <property name="orientation">
         <enum>Qt::Horizontal</enum>
        </property>
        <property name="sizeHint" stdset="0">
         <size>
          <width>40</width>
          <height>20</height>
         </size>
        </property>
       </spacer>
      </item>
     </layout>
    </item>
    <item>
     <widget class="QLabel" name="label_3">
      <property name="text">
       <string>To User</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QLineEdit" name="lineEdit"/>
    </item>
    <item>
     <widget class="QLabel" name="label_6">
      <property name="text">
       <string>Subject</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QLineEdit" name="lineEdit_2"/>
    </item>
    <item>
     <widget class="QLabel" name="label_4">
      <property name="text">
       <string>Message</string>
      </property>
     </widget>
    </item>
    <item>
     <widget class="QLineEdit" name="lineEdit_3"/>
    </item>
    <item>
     <widget class="QPushButton" name="pushButton">
      <property name="text">
       <string>Send</string>
      </property>
     </widget>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>262</width>
     <height>31</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

我将这些 PNG 文件用于对话气泡和红色圆圈:

bubble.png

red_circle.png