Выполнять действия при наведении курсора мыши на QPushButton PyQt5
Я взяла код анимации кнопки при наведении на неё курсора мыши из вопроса. В отдельном проекте с созданием данной кнопки всё работает, но я не могу разобраться, как сделать то же самое, но с уже созданной в Qt Designer кнопкой. Обработка наведения создаётся с помощью этого класса.
class PushButton(QtWidgets.QPushButton):
hover = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(PushButton, self).__init__(parent)
pass
def enterEvent(self, event):
self.hover.emit("enterEvent")
def leaveEvent(self, event):
self.hover.emit("leaveEvent")
Моя попытка сделать это с уже готовой кнопкой:
main.py:
import sys
from PyQt5 import QtCore, QtWidgets, uic
from PyQt5.QtCore import QPropertyAnimation, pyqtProperty
from PyQt5.QtWidgets import QGraphicsDropShadowEffect, QApplication, QMainWindow
class PushButton(QtWidgets.QPushButton):
hover = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(PushButton, self).__init__(parent)
pass
def enterEvent(self, event):
self.hover.emit("enterEvent")
def leaveEvent(self, event):
self.hover.emit("leaveEvent")
class AnimationShadowEffect(QGraphicsDropShadowEffect):
def __init__(self, color, *args, **kwargs):
super(AnimationShadowEffect, self).__init__(*args, **kwargs)
self.setColor(color)
self.setOffset(0, 0)
self.setBlurRadius(0)
self._radius = 0
self.animation = QPropertyAnimation(self)
self.animation.setTargetObject(self)
self.animation.setDuration(1500) # Время одного цикла
self.animation.setLoopCount(-1) # Постоянный цикл
self.animation.setPropertyName(b'radius')
self.animation.setKeyValueAt(0.5, 15)
def start(self):
self.animation.start()
def stop(self, r=0):
# Остановить анимацию и изменить значение радиуса
self.animation.stop()
self.radius = r
@pyqtProperty(int)
def radius(self):
return self._radius
@radius.setter
def radius(self, r):
self._radius = r
self.setBlurRadius(r)
class App(QMainWindow):
def __init__(self):
super(App, self).__init__()
uic.loadUi("Test.ui", self)
#Инифицализация анимации
self.aniButton = AnimationShadowEffect(QtCore.Qt.white, self.designer_button)
self.designer_button.setGraphicsEffect(self.aniButton)
#Добавление эффекта к кнопке
self.designer_button = PushButton(self.designer_button)
self.designer_button.setCheckable(True)
self.designer_button.hover.connect(self.button_hover)
def button_hover(self, hover):
if hover == "enterEvent":
self.aniButton.start()
elif hover == "leaveEvent":
self.aniButton.stop()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
Test.ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<widget name="__qt_fake_top_level">
<widget class="QPushButton" name="designer_button">
<property name="geometry">
<rect>
<x>80</x>
<y>40</y>
<width>201</width>
<height>71</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
background-color: rgb(28, 28, 42);
border: 1px solid rgb(202, 202, 202);
border-radius: 15px;
color: rgb(202, 202, 202);
display: block;
font-family: Calibre, Helvetica Neue, Segoe UI, Helvetica, Arial, Lucida Grande sans-serif;
font-size: 16px;
font-weight: 500;
}
QPushButton:hover {
background-color: rgb(16, 16, 24);
color: rgb(76, 76, 76);
}
QPushButton:pressed {
background-color: rgb(6, 6, 8);
color: rgb(41, 41, 62);
}
</string>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
<resources/>
</ui>
Также залила этот файл на мегу, чтобы сразу можно было использовать его.
Результат выполнения данного кода:
P.S. Также я пробовала способ из вопроса, он также работает, но с его помощью можно отследить только наведение курсора, то есть анимация происходит, но при наведении курсора в другое место, она не пропадает.
Снизу демонстрация того, что мне нужно. Только мне нужно это сделать с кнопкой в подгружаемом файле UI.
Ответы (2 шт):
- Опубликованный
.uiбитый и отличается от того что по ссылке.
Что я сделал:
pyuic5 Test.ui -o Test_ui.py -x- внес изменения в
Test_ui.py:
- Добавил
class PushButton(QtWidgets.QPushButton): ... - Добавил строку
self.designer_button = PushButton(self.centralwidget) - Убрал сроку
display: block;
- Внес изменения в
main.py:
- Добавил
from Test_ui import Ui_MainWindow - Поменял
class AnimationShadowEffect ..., потому что в вашем что-то было не так. - Смотрите строку
class App(QMainWindow, Ui_MainWindow): - Смотрите строку
self.setupUi(self)
main.py
import sys
from PyQt5 import QtCore, QtWidgets, uic
from PyQt5.QtCore import QPropertyAnimation, pyqtProperty
from PyQt5.QtWidgets import QGraphicsDropShadowEffect, QApplication, QMainWindow
from Test_ui import Ui_MainWindow # +++
class AnimationShadowEffect(QGraphicsDropShadowEffect): # Поменял !!!
def __init__(self, color, *args, **kwargs):
super(AnimationShadowEffect, self).__init__(*args, **kwargs)
self.setColor(color)
self.setOffset(0, 0)
self.setBlurRadius(0)
self._radius = 0
self.animation = QPropertyAnimation(self)
self.animation.setTargetObject(self)
self.animation.setDuration(2000) # Время одного цикла
self.animation.setLoopCount(-1) # Постоянный цикл
self.animation.setPropertyName(b'radius')
# Вставить значение
self.animation.setKeyValueAt(0, 1)
self.animation.setKeyValueAt(0.5, 30)
self.animation.setKeyValueAt(1, 1)
def start(self):
self.animation.start()
def stop(self, r=0):
# Остановить анимацию и изменить значение радиуса
self.animation.stop()
self.radius = r
@pyqtProperty(int)
def radius(self):
return self._radius
@radius.setter
def radius(self, r):
self._radius = r
self.setBlurRadius(r)
class App(QMainWindow, Ui_MainWindow): # +++ Ui_MainWindow
def __init__(self):
super(App, self).__init__()
# uic.loadUi("Test_.ui", self)
self.setupUi(self) # +++
self.designer_button.setCheckable(True)
#Инифицализация анимации
self.aniButton = AnimationShadowEffect(QtCore.Qt.white, self.designer_button)
self.designer_button.hover.connect(self.button_hover)
self.designer_button.setGraphicsEffect(self.aniButton)
def button_hover(self, hover):
if hover == "enterEvent":
self.aniButton.start()
elif hover == "leaveEvent":
self.aniButton.stop()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
Test_ui.py
from PyQt5 import QtCore, QtGui, QtWidgets
class PushButton(QtWidgets.QPushButton):
hover = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(PushButton, self).__init__(parent)
pass
def enterEvent(self, event):
self.hover.emit("enterEvent")
def leaveEvent(self, event):
self.hover.emit("leaveEvent")
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(357, 205)
MainWindow.setStyleSheet("background-color: rgb(41, 41, 62);")
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
# self.designer_button = QtWidgets.QPushButton(self.centralwidget)
self.designer_button = PushButton(self.centralwidget) # PushButton
self.designer_button.setGeometry(QtCore.QRect(80, 40, 201, 71))
self.designer_button.setStyleSheet("QPushButton {\n"
" background-color: rgb(28, 28, 42);\n"
" border: 1px solid rgb(202, 202, 202);\n"
" border-radius: 15px;\n"
" color: rgb(202, 202, 202);\n"
" /* display: block; ЭТО НЕ РАБОТАЕТ !!!*/ \n"
" font-family: Calibre, Helvetica Neue, Segoe UI, Helvetica, Arial, Lucida Grande sans-serif;\n"
" font-size: 16px;\n"
" font-weight: 500;\n"
"}\n"
"\n"
"QPushButton:hover { \n"
" background-color: rgb(16, 16, 24);\n"
" color: rgb(76, 76, 76);\n"
"}\n"
"\n"
"QPushButton:pressed { \n"
" background-color: rgb(6, 6, 8);\n"
" color: rgb(41, 41, 62);\n"
"}\n"
"\n"
"")
self.designer_button.setObjectName("designer_button")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 357, 21))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.designer_button.setText(_translate("MainWindow", "PushButton"))
Update
Есть ещё вопрос: если у меня интерфейс в формате
.ui, то мне нужно конвертировать его в.pyи менять инициализацию всех кнопок? С файлом.uiэто невозможно сделать как я поняла?
Все возможно.
Создаете собственный виджет, например
PushButton, который наследуется отQPushButton-> (my_PushButton.py)В Qt Designer заменяем
QPushButtonнаPushButton
- Все, запускаем
main.py
main.py
import sys
from PyQt5 import QtCore, QtWidgets, uic
from PyQt5.QtCore import QPropertyAnimation, pyqtProperty
from PyQt5.QtWidgets import QGraphicsDropShadowEffect, QApplication, QMainWindow
#from Test_ui import Ui_MainWindow
class AnimationShadowEffect(QGraphicsDropShadowEffect):
def __init__(self, color, *args, **kwargs):
super(AnimationShadowEffect, self).__init__(*args, **kwargs)
self.setColor(color)
self.setOffset(0, 0)
self.setBlurRadius(0)
self._radius = 0
self.animation = QPropertyAnimation(self)
self.animation.setTargetObject(self)
self.animation.setDuration(2000) # Время одного цикла
self.animation.setLoopCount(-1) # Постоянный цикл
self.animation.setPropertyName(b'radius')
# Вставить значение
self.animation.setKeyValueAt(0, 1)
self.animation.setKeyValueAt(0.5, 30)
self.animation.setKeyValueAt(1, 1)
def start(self):
self.animation.start()
def stop(self, r=0):
# Остановить анимацию и изменить значение радиуса
self.animation.stop()
self.radius = r
@pyqtProperty(int)
def radius(self):
return self._radius
@radius.setter
def radius(self, r):
self._radius = r
self.setBlurRadius(r)
class App(QMainWindow): #, Ui_MainWindow):
def __init__(self):
super(App, self).__init__()
uic.loadUi("Test_333.ui", self) # +++
# self.setupUi(self)
self.designer_button.setCheckable(True)
#Инифицализация анимации
self.aniButton = AnimationShadowEffect(QtCore.Qt.white, self.designer_button)
self.designer_button.hover.connect(self.button_hover)
self.designer_button.setGraphicsEffect(self.aniButton)
def button_hover(self, hover):
if hover == "enterEvent":
self.aniButton.start()
elif hover == "leaveEvent":
self.aniButton.stop()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
ex.show()
sys.exit(app.exec_())
my_PushButton.py
from PyQt5 import QtCore, QtGui, QtWidgets
class PushButton(QtWidgets.QPushButton):
hover = QtCore.pyqtSignal(str)
def __init__(self, parent=None):
super(PushButton, self).__init__(parent)
pass
def enterEvent(self, event):
self.hover.emit("enterEvent")
def leaveEvent(self, event):
self.hover.emit("leaveEvent")
Test_333.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>357</width>
<height>205</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(41, 41, 62);</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="PushButton" name="designer_button">
<property name="geometry">
<rect>
<x>80</x>
<y>40</y>
<width>201</width>
<height>71</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">QPushButton {
background-color: rgb(28, 28, 42);
border: 1px solid rgb(202, 202, 202);
border-radius: 15px;
color: rgb(202, 202, 202);
font-family: Calibre, Helvetica Neue, Segoe UI, Helvetica, Arial, Lucida Grande sans-serif;
font-size: 16px;
font-weight: 500;
}
QPushButton:hover {
background-color: rgb(16, 16, 24);
color: rgb(76, 76, 76);
}
QPushButton:pressed {
background-color: rgb(6, 6, 8);
color: rgb(41, 41, 62);
}
</string>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>357</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<customwidgets>
<customwidget>
<class>PushButton</class>
<extends>QPushButton</extends>
<header>my_PushButton</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
Спасибо! Мне это тоже помогло. Как раз искал что то подобное. Есть один нюанс. Все работает в pycharm, но после конвертации проекта в .exe Проект не запускается в введу отсутствия нужно файла. Я думаю дело в my_PushButton.py нужно его как-то подгрузить что-ли. Без него все было хорошо.




