Как прятать мышь в реальном времени Pyside6

Я пытаюсь прятать мышь в зависимости от её положения на экране, я сделал код который отслеживает мышь в реальном времени и прячет курсор если положение не менялось.

Но я столкнулся с одной проблемой, когда я меняю тип мыши (setCursor), мне нужно вынести мышь из окна и завести в него заново чтобы она действительно перестала отображаться.

Если вкратце то мышь попросту не прячется до тех пор пока мышь не покинет окно и не попадет в него обратно. (Это моя проблема)

Мой код:

import sys
import time

from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import QSize, QMetaObject, QCoreApplication, QRect, Qt
from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QWidget, QGridLayout, QListWidget, QMenuBar, QStatusBar, \
    QMainWindow
from functools import partial
from threading import Thread
class Ui_Form(object):
    def setupUi(self, Form):
        if not Form.objectName():
            Form.setObjectName(u"Form")
        Form.resize(291, 53)
        self.horizontalLayout = QHBoxLayout(Form)
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.label = QLabel(Form)
        self.label.setObjectName(u"label")
        self.label.setMinimumSize(QSize(200, 20))

        self.horizontalLayout.addWidget(self.label)

        self.pushButton = QPushButton(Form)
        self.pushButton.setObjectName(u"pushButton")
        self.pushButton.setMinimumSize(QSize(50, 20))

        self.horizontalLayout.addWidget(self.pushButton)

        self.retranslateUi(Form)

        QMetaObject.connectSlotsByName(Form)

    # setupUi

    def retranslateUi(self, Form):
        Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
        self.label.setText(QCoreApplication.translate("Form",
                                                      u"\u0422\u0443\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0442\u0435\u043a\u0441\u0442",
                                                      None))
        self.pushButton.setText(QCoreApplication.translate("Form", u"PushButton", None))
    # retranslateUi


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setMouseTracking(True)
        self.centralwidget.setObjectName(u"centralwidget")
        self.gridLayout = QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName(u"gridLayout")
        self.listWidget = QListWidget(self.centralwidget)
        self.listWidget.setObjectName(u"listWidget")

        self.gridLayout.addWidget(self.listWidget, 0, 0, 1, 1)

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setObjectName(u"menubar")
        self.menubar.setGeometry(QRect(0, 0, 800, 22))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)

        QMetaObject.connectSlotsByName(MainWindow)


# class TestWidget(QtWidgets.QMainWindow, Ui_Form):
#                          vvvvvvv
class TestWidget(QtWidgets.QWidget, Ui_Form):  # +++
    def __init__(self, parent=None):
        super(TestWidget, self).__init__(parent)
        self.setupUi(self)

    # setupUi

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))

    # retranslateUi

    def setText(self, text):
        self.label.setText(text)

    def sizeHint(self):
        return QSize(200, 40)


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        self.show()
        self.setMouseTracking(True)
        for i in range(20):
            testwidget = TestWidget()
            item = QtWidgets.QListWidgetItem(self.listWidget)
            testwidget.setText(f"Это элемент {i}")
            # +++
            #            testwidget.pushButton.clicked.connect(lambda: self.test(i))
            testwidget.pushButton.clicked[bool].connect(lambda ch, i=i: self.test(i))  # +++

            item.setSizeHint(testwidget.sizeHint())
            self.listWidget.addItem(item)
            self.listWidget.setItemWidget(item, testwidget)
        self.oldxposition = 0
        self.oldyposition = 0
        self.xposition = 1
        self.yposition = 1
        self.th_1 = Thread(target=self.test2)
        self.th_1.start()
        self.listWidget.setMouseTracking(True)

    def mouseMoveEvent(self, event):
        self.xposition = int(event.position().x())
        self.yposition = int(event.position().y())
        print(self.xposition, self.yposition)


    def test2(self):
        while True:
            print(f"X старый: {self.oldxposition}, X новый: {self.xposition}, Y Старый: {self.oldyposition}, Y новый: {self.yposition}")
            if int(self.oldxposition) == int(self.xposition) and int(self.yposition) == int(self.oldyposition):
                self.setCursor(Qt.BlankCursor)
                print("Сработал")
            else:
                self.oldyposition = self.yposition
                self.oldxposition = self.xposition
                self.unsetCursor()
                print("Не сработал")
            time.sleep(1)



if __name__ == "__main__":
    if not QtWidgets.QApplication.instance():
        app = QtWidgets.QApplication(sys.argv)
    else:
        app = QtWidgets.QApplication.instance()
    window = MainWindow()
    sys.exit(app.exec())

Ответы (1 шт):

Автор решения: S. Nick

Я не совсем уверен, что правильно вас понял.

Обратите внимание:

  • вам не нужен дополнительный поток в вашей задаче. Вам достаточно использовать QTimer.

  • я добавил класс ListWidget и перенес туда обработчик события mouseMoveEvent


import sys
#- import time
'''
from PySide6 import QtCore, QtGui, QtWidgets
from PySide6.QtCore import QSize, QMetaObject, QCoreApplication, QRect, Qt
from PySide6.QtWidgets import QHBoxLayout, QLabel, QPushButton, QWidget, QGridLayout, QListWidget, QMenuBar, QStatusBar, \
    QMainWindow
'''
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *    
    
#from functools import partial
#- from threading import Thread


class Ui_Form(object):
    def setupUi(self, Form):
        if not Form.objectName():
            Form.setObjectName(u"Form")
        Form.resize(291, 53)
        self.horizontalLayout = QHBoxLayout(Form)
        self.horizontalLayout.setObjectName(u"horizontalLayout")
        self.label = QLabel(Form)
        self.label.setObjectName(u"label")
        self.label.setMinimumSize(QSize(200, 20))
        self.horizontalLayout.addWidget(self.label)

        self.pushButton = QPushButton(Form)
        self.pushButton.setObjectName(u"pushButton")
        self.pushButton.setMinimumSize(QSize(50, 20))
        self.horizontalLayout.addWidget(self.pushButton)

        self.retranslateUi(Form)
        QMetaObject.connectSlotsByName(Form)


    def retranslateUi(self, Form):
        Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None))
        self.label.setText(QCoreApplication.translate("Form",
                                                      u"\u0422\u0443\u0442 \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u0442\u0435\u043a\u0441\u0442",
                                                      None))
        self.pushButton.setText(QCoreApplication.translate("Form", u"PushButton", None))


# +++ vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
class ListWidget(QtWidgets.QListWidget):
    def __init__(self, parent=None):
        super(ListWidget, self).__init__(parent)
        
        self.xposition = 1
        self.yposition = 1

    def mouseMoveEvent(self, event):
#        self.xposition = int(event.position().x())                             # PySide6
#        self.yposition = int(event.position().y())                             # PySide6
        self.xposition = int(event.pos().x())                            # PyQt5
        self.yposition = int(event.pos().y())                            # PyQt5
        
        print(self.xposition, self.yposition, '-----------------------------------------')            
    
        super(ListWidget, self).mouseMoveEvent(event)
# +++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        if not MainWindow.objectName():
            MainWindow.setObjectName(u"MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QWidget(MainWindow)
        self.centralwidget.setMouseTracking(True)
        self.centralwidget.setObjectName(u"centralwidget")
        self.gridLayout = QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName(u"gridLayout")
        
#        self.listWidget = QListWidget(self.centralwidget)
        self.listWidget = ListWidget(self.centralwidget)                             # !!! +++ 
        
        self.listWidget.setObjectName(u"listWidget")

        self.gridLayout.addWidget(self.listWidget, 0, 0, 1, 1)

        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QMenuBar(MainWindow)
        self.menubar.setObjectName(u"menubar")
        self.menubar.setGeometry(QRect(0, 0, 800, 22))
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QStatusBar(MainWindow)
        self.statusbar.setObjectName(u"statusbar")
        MainWindow.setStatusBar(self.statusbar)

        QMetaObject.connectSlotsByName(MainWindow)


class TestWidget(QtWidgets.QWidget, Ui_Form):  
    def __init__(self, parent=None):
        super(TestWidget, self).__init__(parent)
        self.setupUi(self)

    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(QCoreApplication.translate("MainWindow", u"MainWindow", None))

    def setText(self, text):
        self.label.setText(text)

    def sizeHint(self):
        return QSize(200, 40)


class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.setupUi(self)
        self.show()
        self.setMouseTracking(True)
        for i in range(20):
            testwidget = TestWidget()
            item = QtWidgets.QListWidgetItem(self.listWidget)
            testwidget.setText(f"Это элемент {i}")
            testwidget.pushButton.clicked[bool].connect(lambda ch, i=i: self.test(i))

            item.setSizeHint(testwidget.sizeHint())
            self.listWidget.addItem(item)
            self.listWidget.setItemWidget(item, testwidget)
            
        self.oldxposition = 0
        self.oldyposition = 0
        
#        self.xposition = 1
#        self.yposition = 1
        
#        self.th_1 = Thread(target=self.test2)
#        self.th_1.start()

        self.timer = QtCore.QTimer(self)                                                     # +++
        self.timer.timeout.connect(self.test2)                                               # +++
        self.timer.start(1000)                                                               # +++
        
        self.listWidget.setMouseTracking(True)

    '''
    def mouseMoveEvent(self, event):
#        self.xposition = int(event.position().x())                           # PySide6
#        self.yposition = int(event.position().y())                           # PySide6
        self.xposition = int(event.pos().x())                            # PyQt5
        self.yposition = int(event.pos().y())                            # PyQt5
        print(self.xposition, self.yposition)
    
    def test2(self):
        while True:
            print(f"X старый: {self.oldxposition}, X новый: {self.xposition}, Y Старый: {self.oldyposition}, Y новый: {self.yposition}")
            if int(self.oldxposition) == int(self.xposition) and int(self.yposition) == int(self.oldyposition):
                self.setCursor(Qt.BlankCursor)
                print("Сработал")
            else:
                self.oldyposition = self.yposition
                self.oldxposition = self.xposition
                self.unsetCursor()
                print("Не сработал")
            time.sleep(1)
    '''
    
    def test2(self):
        print(f"X старый: {self.oldxposition}, X новый: {self.listWidget.xposition}, "
              f"\nY Старый: {self.oldyposition}, Y новый: {self.listWidget.yposition}")
        if int(self.oldxposition) == int(self.listWidget.xposition) and \
           int(self.listWidget.yposition) == int(self.oldyposition):
            self.setCursor(Qt.BlankCursor)
            print("Сработал")
        else:
            self.oldyposition = self.listWidget.yposition
            self.oldxposition = self.listWidget.xposition
            self.unsetCursor()
            print("Не сработал")

    def test(self, i):                                                                   # +++
        print(f'def test(self, i): это элемент {i}')                                     # +++


if __name__ == "__main__":
    if not QtWidgets.QApplication.instance():
        app = QtWidgets.QApplication(sys.argv)
    else:
        app = QtWidgets.QApplication.instance()
    window = MainWindow()
    sys.exit(app.exec())

введите сюда описание изображения

→ Ссылка