1

Пытаясь создать анимированные кнопки при наведении в активном окне, воспользовался подсказкой из этого вопроса.
Использовал конструкцию условия чтобы определить какая кнопка, какую анимацию должна проигрывать, но вместо ожидаемого, получил результат, при котором анимацию проигрывает только средняя кнопка.
А если быстро провести курсором по кнопкам, то анимация и вовсе пропадает и появляется лишь тогда, когда окно перезапущено.

Таким образом вырисовывается две проблемы:

  1. Анимация проигрывается только на средней кнопке, остальные лишь тригерят проигрывание анимации на средней кнопке.
  2. Анимация ломается и больше не воспроизводится если по всему ряду кнопок провести курсором не останавливаясь.
import sys
import os
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5.QtCore import *
from PyQt5.QtGui import QIcon, QPixmap
from PyQt5.QtWidgets import *

class Window(QWidget): def init(self, parent=None): super(Window, self).init(parent) self.resize(310, 105) self.angle = 0 self.val = 0 self.i = 0

min_button

    self.image_fname_min_button = ('icons/cil-minus.png')
    self.min_button = QPushButton(self)
    self.min_button.resize(100, 100)
    self.min_button.setIcon(
        QIcon(QPixmap(self.image_fname_min_button)))
    # Animation min_button
    self.min_button.installEventFilter(self)
    self.timer_min_button = QtCore.QTimer()
    self.timer_min_button.timeout.connect(
        lambda: self.onRotate('min_button', self.val))

max_button

    self.image_fname_max_button = ('icons/cil-fullscreen.png')
    self.max_button = QPushButton(self)
    self.max_button.move(105, 0)
    self.max_button.resize(100, 100)
    self.max_button.setIcon(
        QIcon(QPixmap(self.image_fname_max_button)))
    # Animation max_button
    self.max_button.installEventFilter(self)
    self.timer_max_button = QtCore.QTimer()
    self.timer_max_button.timeout.connect(
        lambda: self.onRotate('max_button', self.val))

close_button

    self.image_fname_close_button = ('icons/cil-power-standby.png')
    self.close_button = QPushButton(self)
    self.close_button.move(210, 0)
    self.close_button.resize(100, 100)
    self.close_button.setIcon(
        QIcon(QPixmap(self.image_fname_close_button)))
    # Animation close_button
    self.close_button.installEventFilter(self)
    self.timer_close_button = QtCore.QTimer()
    self.timer_close_button.timeout.connect(
        lambda: self.onRotate('close_button', self.val))

def eventFilter(self, obj, event):
    if self.min_button is obj:
        if event.type() == QtCore.QEvent.Enter:
            self.val = 1
            self.timer_min_button.start(60)
        elif event.type() == QtCore.QEvent.Leave:
            self.val = -1
            self.timer_min_button.start(80)
    elif self.max_button is obj:
        if event.type() == QtCore.QEvent.Enter:
            self.val = 1
            self.timer_max_button.start(60)
        elif event.type() == QtCore.QEvent.Leave:
            self.val = -1
            self.timer_max_button.start(80)
    elif self.close_button is obj:
        if event.type() == QtCore.QEvent.Enter:
            self.val = 1
            self.timer_close_button.start(60)
        elif event.type() == QtCore.QEvent.Leave:
            self.val = -1
            self.timer_close_button.start(80)
    return super().eventFilter(obj, event)

def onRotate(self, name_button, val=0):
    self.i += val
    self.angle += 45 * val
    if self.angle <= 90 and self.angle >= -90:
        t = QtGui.QTransform().rotate(self.angle)
        if name_button == 'min_button':
            print('Ветка min_button')
            pix = QtGui.QPixmap(self.image_fname_min_button).transformed(t)
            image_rotated_min_button = f'{os.path.splitext(self.image_fname_min_button)[0]}_rotated.png'
            pix.save(image_rotated_min_button)
            self.max_button.setIcon(QtGui.QIcon(image_rotated_min_button))
        elif name_button == 'max_button':
            print('Ветка max_button')
            pix = QtGui.QPixmap(self.image_fname_max_button).transformed(t)
            image_rotated_max_button = f'{os.path.splitext(self.image_fname_max_button)[0]}_rotated.png'
            pix.save(image_rotated_max_button)
            self.max_button.setIcon(QtGui.QIcon(image_rotated_max_button))
        elif name_button == 'close_button':
            print('Ветка close_button')
            pix = QtGui.QPixmap(
                self.image_fname_close_button).transformed(t)
            image_rotated_close_button = f'{os.path.splitext(self.image_fname_close_button)[0]}_rotated.png'
            pix.save(image_rotated_close_button)
            self.max_button.setIcon(
                QtGui.QIcon(image_rotated_close_button))
    else:
        self.timer_min_button.stop()
        self.timer_max_button.stop()
        self.timer_close_button.stop()


if name == "main": app = QApplication(sys.argv) window = Window() window.show() sys.exit(app.exec_())

Помогите понять что я делаю не так.

S. Nick
  • 74,889
PandaStock
  • 336
  • 2
  • 10

1 Answers1

1

Попробуйте так:

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.Qt import *

class PushButton(QPushButton): def init(self, img, args, kwargs): super(PushButton, self).init(args, **kwargs)

    self.rotation = 0
    self.amount_rotation = 0
    self.angle = 45

    self.pixmap = QPixmap(img)
    self._width = self.pixmap.size().width()
    self._height = self.pixmap.size().height()
    self.pixmap = self.pixmap.scaled(self._width, self._height)

    pm = QPixmap(self._width, self._height)
    rectF = QRectF(0, 0, self._width, self._height)  
    painter = QPainter(pm)
    painter.drawPixmap(rectF, self.pixmap, rectF)
    painter.end()

    self.setIcon(QIcon(pm))
    self.setIconSize(QSize(50, 50))

    self.timer = QtCore.QTimer()
    self.timer.timeout.connect(self.rotate_item)

def rotate_item(self):
    if (self.angle > 0 and self.amount_rotation >= 7) or \
       (self.angle < 0 and self.amount_rotation <= 0):

        self.timer.stop()
        return

    self.rotation = (self.rotation + self.angle) % 360

    rectF = QRectF(0, 0, self._width, self._height)   
    pix = QPixmap(self._width, self._height)
    painter = QPainter(pix)
    painter.translate(rectF.center()) 
    painter.rotate(self.rotation)
    painter.translate(-rectF.center())
    painter.drawPixmap(0, 0, self.pixmap)
    painter.end()

    self.setIcon(QIcon(pix))

    if self.angle > 0:
        self.amount_rotation += 1
    else:
        self.amount_rotation -= 1

def enterEvent(self, event):
    self.angle = 45        
    self.timer.stop()
    self.timer.start(100)

def leaveEvent(self, event):
    self.angle = -45        
    self.timer.stop()
    self.timer.start(100)


class Window(QWidget): def init(self): super().init()

    self.min_button = PushButton("lena50.png", self)
    self.max_button = PushButton("monkey50.png", self)
    self.close_button = PushButton("orig50.jpg", self)

    layout = QHBoxLayout(self)
    layout.addWidget(self.min_button)
    layout.addWidget(self.max_button)
    layout.addWidget(self.close_button)


if name=="main": app = QApplication(sys.argv) w = Window() w.show() sys.exit(app.exec_())

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


lena50.png

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

monkey50.png

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

orig50.jpg

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

S. Nick
  • 74,889