短腿老爷们儿 2025-12-02 03:52 采纳率: 0%
浏览 2

pyside6 enterEvent鼠标移入事件不触发,但是会触发鼠标移出事件,为什么会这样

pyside6 在移动窗口后有时鼠标移入事件不触发


```python


import sys
from typing import Tuple
import uuid
from PySide6.QtWidgets import QMainWindow,QScrollArea,QComboBox,QLineEdit,QRadioButton,QApplication,QWidget,QLabel,QPushButton,QSizePolicy,QButtonGroup,QPlainTextEdit
from PySide6.QtSvgWidgets import QSvgWidget
from styles.style_manager import manager_style,AutoHBoxLayout,AutoVBoxLayout
from PySide6.QtCore import QParallelAnimationGroup,QSequentialAnimationGroup,Qt,QPropertyAnimation,Property,QEvent,QEasingCurve,QObject, Signal,QSize,QTimer,QRect,QPoint
from PySide6.QtGui import QCursor,QTextBlockFormat,QTextCursor,QColor,QFontMetrics,QIcon,QPixmap,QMouseEvent,QEnterEvent,QFont,QBitmap,QPainter,QPen,QRadialGradient,QPainterPath
from PySide6.QtWidgets import QScrollBar, QStyle, QStyleOptionSlider, QVBoxLayout
from PySide6.QtCore import Qt, QTimer, QEvent
from PySide6.QtGui import QEnterEvent
from PySide6.QtGui import QBrush
from PySide6.QtGui import QRegularExpressionValidator
from PySide6.QtCore import QRegularExpression

import PySide6
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QGraphicsDropShadowEffect


h=34

class Top_bar(QWidget):
    def __init__(self,parent=None):
        super().__init__(parent)

        self.is_open_menu=False
        self.setFixedSize(all_with,h)

        box=QWidget(self)
        box.setObjectName("box")
        box.setFixedSize(all_with, h) 




        self.setStyleSheet(manager_style.top_bar_style())
        self.enter =  QColor(0, 0, 0)
        self.leave= QColor(255, 255, 255)

        self.update_ui()



    def enterEvent(self, event:QEnterEvent):
        self.setStyleSheet(f"""
            #box{{
            background-color: {self.enter.name()};
            border:1px solid rgba(170, 170, 170, 1);
            border-top-left-radius:6px;
            border-top-right-radius:6px;
            border-bottom:none;
            }}
        """)


    def leaveEvent(self, event:QEnterEvent):
        self.setStyleSheet(f"""
            #box{{
            background-color: {self.leave.name()};
            border:1px solid rgba(170, 170, 170, 1);
            border-top-left-radius:6px;
            border-top-right-radius:6px;

            border-bottom:none;
            }}
        """)


    def update_ui(self):
        self.setStyleSheet(f"""
            #box{{
            background-color: {self.leave.name()};
            border:1px solid rgba(170, 170, 170, 1);
            border-top-left-radius:6px;
            border-top-right-radius:6px;

            border-bottom:none;
            }}
        """)


all_with=350

#透明的容器
class MainWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.setFocusPolicy(Qt.ClickFocus)
        #隐藏标题栏
        self.setWindowFlags(Qt.FramelessWindowHint)
        #设置透明背景属性
        self.setAttribute(Qt.WA_TranslucentBackground)
        #不接受鼠标事件
        # self.setAttribute(Qt.WA_TransparentForMouseEvents) 

        layout=QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)   
        layout.setSpacing(0) 
        layout.setAlignment(Qt.AlignLeft | Qt.AlignTop )

        top_bar1=Top_bar()
        layout.addWidget(top_bar1)

        top_bar2=Top_bar()
        layout.addWidget(top_bar2)

        self.top_bar=Top_bar()
        layout.addWidget(self.top_bar)



        self.setFixedSize(all_with,h*3)







        self.setStyleSheet(manager_style.main_style())
        self.dragging = False 

        self.top_bar.installEventFilter(self)
    def eventFilter(self, obj, event):
        # print(obj, event)
        if obj == self.top_bar:
            event_type = event.type()
            # 鼠标按下
            if event_type == QEvent.MouseButtonPress:
                if event.button() == Qt.LeftButton:
                    self.dragging = True
                    self.drag_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
                    return True
            # 鼠标移动
            elif event_type == QEvent.MouseMove:

                if self.dragging and (event.buttons() & Qt.LeftButton):
                    
                    self.move(event.globalPosition().toPoint() - self.drag_position)
                    return True
            # 鼠标释放
            elif event_type == QEvent.MouseButtonRelease:
                if event.button() == Qt.LeftButton:
                    self.dragging = False
                    return True

        return super().eventFilter(obj, event)
        

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

```

  • 写回答

2条回答 默认 最新

  • 檀越@新空间 2025-12-02 09:26
    关注

    上午好☀️☀️☀️️
    本答案参考通义千问

    在使用 PySide6 时,enterEvent 鼠标移入事件不触发,但 leaveEvent 鼠标移出事件却能正常触发,这通常与以下几个原因有关:


    ✅ 可能的原因分析

    1. 控件未正确设置接受鼠标事件的标志
    2. 控件被其他控件遮挡或覆盖
    3. 控件本身没有“可见区域”导致无法触发 enterEvent
    4. 窗口移动后,事件传递机制出现问题

    🔍 解决方案

    1. 确保控件能够接收鼠标事件

    默认情况下,某些控件(如 QLabelQWidget)可能不会自动接收鼠标事件。你需要确保你的控件设置了正确的标志。

    重点:必须设置 Qt.WidgetQt.WA_Hover 属性以启用鼠标悬停事件。

    # 在控件初始化时添加以下代码
    self.setAttribute(Qt.WA_Hover, True)  # 启用 hover 事件
    

    2. 检查控件是否被遮挡

    如果控件被其他控件覆盖(比如子控件),那么鼠标事件可能被拦截,导致 enterEvent 不触发。

    重点:检查布局中是否有其他控件覆盖了目标控件。


    3. 确保控件有实际的大小和可见区域

    如果你的控件尺寸为 0 或者没有设置 setFixedSize(),则它不会产生任何鼠标事件。

    重点:确保控件具有有效的宽度和高度。


    4. 使用 eventFilter 监听父级事件

    有时候,直接在控件上监听 enterEvent 会失效,可以尝试在父控件中使用 eventFilter 来捕获事件。

    重点:通过 eventFilter 可以更灵活地控制事件流。


    5. 窗口移动后触发 enterEvent 的问题

    当窗口移动后,系统可能会重新计算事件的坐标,导致部分事件丢失。你可以尝试在窗口移动后强制刷新控件的状态。

    重点:使用 update() 方法强制控件重绘。


    ✅ 修改后的代码示例

    以下是修改后的 Top_bar 类,确保 enterEventleaveEvent 正常工作:

    import sys
    from PySide6.QtWidgets import QWidget, QStyle, QStyleOptionSlider, QVBoxLayout, QApplication
    from PySide6.QtCore import Qt, QEvent
    from PySide6.QtGui import QColor
    
    
    class Top_bar(QWidget):
        def __init__(self, parent=None):
            super().__init__(parent)
    
            self.is_open_menu = False
            self.setFixedSize(350, 34)  # 设置固定大小
    
            # 确保控件可以接收 hover 事件
            self.setAttribute(Qt.WA_Hover, True)
    
            box = QWidget(self)
            box.setObjectName("box")
            box.setFixedSize(350, 34)
    
            self.setStyleSheet(manager_style.top_bar_style())
            self.enter = QColor(0, 0, 0)
            self.leave = QColor(255, 255, 255)
    
            self.update_ui()
    
        def enterEvent(self, event: QEnterEvent):
            self.setStyleSheet(f"""
                #box{{
                    background-color: {self.enter.name()};
                    border: 1px solid rgba(170, 170, 170, 1);
                    border-top-left-radius: 6px;
                    border-top-right-radius: 6px;
                    border-bottom: none;
                }}
            """)
    
        def leaveEvent(self, event: QEnterEvent):
            self.setStyleSheet(f"""
                #box{{
                    background-color: {self.leave.name()};
                    border: 1px solid rgba(170, 170, 170, 1);
                    border-top-left-radius: 6px;
                    border-top-right-radius: 6px;
                    border-bottom: none;
                }}
            """)
    
        def update_ui(self):
            self.setStyleSheet(f"""
                #box{{
                    background-color: {self.leave.name()};
                    border: 1px solid rgba(170, 170, 170, 1);
                    border-top-left-radius: 6px;
                    border-top-right-radius: 6px;
                    border-bottom: none;
                }}
            """)
    

    🛠 补充建议

    1. 使用 QGraphicsDropShadowEffect 时注意事件穿透

    如果你在控件上添加了阴影效果(如 QGraphicsDropShadowEffect),它可能导致事件被“穿透”,即鼠标事件不会被正确触发。

    重点:确保阴影效果不影响事件传递。


    2. 检查窗口是否设置了 Qt.FramelessWindowHint

    如果你使用了无边框窗口(Qt.FramelessWindowHint),并且没有处理鼠标事件,那么整个窗口的事件行为可能变得不可预测。

    重点:如果使用无边框窗口,请自行实现拖动等逻辑。


    ✅ 总结

    | 原因 | 解决方法 | |------|----------| | 控件未设置 WA_Hover | 添加 self.setAttribute(Qt.WA_Hover, True) | | 控件被遮挡 | 检查布局结构,确保控件可见 | | 控件尺寸为 0 | 设置 setFixedSize() | | 窗口移动后事件异常 | 使用 update() 强制刷新 | | 事件被拦截 | 使用 eventFilter 捕获事件 |


    如有更多关于事件处理的问题,欢迎继续提问!

    评论

报告相同问题?

问题事件

  • 修改了问题 12月2日
  • 修改了问题 12月2日
  • 创建了问题 12月2日