如果我將滑鼠移動得如此之快,它就會變得混亂,并且“關閉”影片<=不起作用。
我正在努力計算影片QRect并在影片已經運行時處理它。
目標是創建類似于此 gif 中的平滑影片效果:

uj5u.com熱心網友回復:
我認為您遇到問題的原因是因為當您離開小部件時,您將開始影片設定為按鈕可以采用的最大寬度,而不是從當前寬度開始。我已經QPushButton通過以下方式實作了我自己的子類,這似乎可以達到您需要的結果。我不會創建事件過濾器,而是覆寫進入和離開事件。每次移動小部件或調整大小(在影片之外)時,我們還需要更新初始幾何圖形,因此我也覆寫了移動和調整大小事件。
// MyButton.h
class MyButton : public QPushButton
{
public:
MyButton(QWidget* parent = nullptr);
~MyButton() = default;
protected:
void enterEvent(QEvent *event) override;
void leaveEvent(QEvent* event) override;
void moveEvent(QMoveEvent *event) override;
void resizeEvent(QResizeEvent* event) override;
private:
QPropertyAnimation* m_animation;
QRect m_init_geometry;
double m_duration;
double m_extension;
};
這是實作:
// MyButton.cpp
MyButton::MyButton(QWidget* parent)
: QPushButton(parent)
, m_animation(nullptr)
, m_init_geometry()
, m_duration(200)
, m_extension(100)
{
m_animation = new QPropertyAnimation(this, "geometry", this);
m_animation->setDuration(m_duration);
m_animation->setEasingCurve(QEasingCurve::Linear);
m_init_geometry = geometry();
}
void MyButton::enterEvent(QEvent *event)
{
QPushButton::enterEvent(event);
m_animation->stop();
// update the duration so that we get a uniform speed when triggering this animation midway
m_animation->setDuration(((m_init_geometry.width() m_extension - width())/m_extension)*m_duration);
m_animation->setStartValue(geometry());
m_animation->setEndValue(QRectF(m_init_geometry.x(), m_init_geometry.y(), m_init_geometry.width() m_extension, m_init_geometry.height()));
m_animation->start();
}
void MyButton::leaveEvent(QEvent *event)
{
QPushButton::leaveEvent(event);
m_animation->stop();
// update the duration so that we get a uniform speed when triggering this animation midway
m_animation->setDuration(((width() - m_init_geometry.width())/m_extension)*m_duration);
m_animation->setStartValue(geometry());
m_animation->setEndValue(m_init_geometry);
m_animation->start();
}
void MyButton::moveEvent(QMoveEvent *event)
{
// ignore the move event if it's due to the animation, otherwise store the new geometry
if(m_animation->state() == QPropertyAnimation::Running) return;
QPushButton::moveEvent(event);
m_init_geometry.setTopLeft(event->pos());
}
void MyButton::resizeEvent(QResizeEvent *event)
{
// ignore the move event if it's due to the animation, otherwise store the new geometry
if(m_animation->state() == QPropertyAnimation::Running) return;
QPushButton::resizeEvent(event);
m_init_geometry.setSize(event->size());
}
請注意,關閉影片的起始值是當前幾何體,而不是初始幾何體加上擴展寬度。我正在更新線性減少打開影片的持續時間,具體取決于當前寬度與完整擴展寬度的接近程度;結束影片也是如此。現在其余的與您的代碼非常相似:
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
auto* btn = new MyButton(this);
btn->setGeometry(100, 100, 60, 80);
btn->setStyleSheet(R"(QPushButton {
background-image: url(:/ubuntu.png);
background-repeat: no-repeat;
background-origin: content;
background-position: left center;}
)");
auto* labl = new QLabel("Hello World", btn);
labl->setAlignment(Qt::AlignCenter);
labl->setGeometry(btn->width(), 0, labl->width(), btn->height());
}
結果看起來像這樣

uj5u.com熱心網友回復:
我嘗試這種方式:
在 mybutton.h
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include <QLabel>
#include <QPushButton>
class MyButton : public QPushButton
{
Q_OBJECT
public:
MyButton(QWidget* parent = nullptr);
// QObject interface
public:
bool eventFilter(QObject *watched, QEvent *event);
signals:
void mouseEnter();
void mouseLeave();
private:
};
#endif // MYBUTTON_H
在 mybutton.cpp
#include "mybutton.h"
#include <QEvent>
#include <QLabel>
MyButton::MyButton(QWidget *parent):
QPushButton(parent)
{
}
bool MyButton::eventFilter(QObject *watched, QEvent *event)
{
if (event->type() == QEvent::HoverEnter)
{
emit mouseEnter();
}
else if (event->type() == QEvent::HoverLeave)
{
emit mouseLeave();
}
}
我使用信號并在 MainWindow 類 UI 中添加小部件和布局:

在主視窗.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLabel>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
QLabel *labl;
QLabel *labl2;
};
#endif // MAINWINDOW_H
在主視窗.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <mybutton.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
MyButton* btn = new MyButton(this);
btn->setObjectName("button 1 ");
btn->setText("btn 1");
btn->setGeometry(ui->widget->x(), 100, 50, 50);
ui->widget->layout()->addWidget(btn);
// QLabel
labl= new QLabel(btn,Qt::ToolTip);
connect(btn,&MyButton::mouseEnter,this,[btn,this](){
labl->setObjectName("label");
labl->setGeometry(btn->x() this->x() btn->width() 10, btn->y() this->y() btn->height() 15,
labl->width(), labl->height());
labl->setText("Hello World");
labl->setAlignment(Qt::AlignCenter);
labl->show();
});
connect(btn,&MyButton::mouseLeave,this,[this](){
labl->hide();
});
btn->installEventFilter(btn);
MyButton* btn2 = new MyButton(this);
btn2->setObjectName("button 2 ");
btn2->setText("btn 2");
btn2->setGeometry(ui->widget->x(), 100, 50, 50);
ui->widget->layout()->addWidget(btn2);
// QLabel
labl2= new QLabel(btn2,Qt::ToolTip);
connect(btn2,&MyButton::mouseEnter,this,[btn2,this](){
labl2->setObjectName("label");
labl2->setGeometry(btn2->x() this->x() btn2->width() 10, btn2->y() this->y() btn2->height() 15,
labl2->width(), labl2->height());
labl2->setText("Hello World 2");
labl2->setAlignment(Qt::AlignCenter);
labl2->show();
});
connect(btn2,&MyButton::mouseLeave,this,[this](){
labl2->hide();
});
btn->installEventFilter(btn);
btn2->installEventFilter(btn2);
}
MainWindow::~MainWindow()
{
delete ui;
}
這是我的結果:

通過在樣式表中使用相同的顏色,您可以擁有您在 Gif 中顯示的內容。
uj5u.com熱心網友回復:
您可以嘗試這種方法:只計算一次開始和結束矩形并在影片物件中設定。
在輸入時,您像以前一樣開始影片。在休假時,您可以將影片的方向從向前播放更改為向后播放。
您可以使用向后運行影片
this->anim->setDirection( QAbstractAnimation::Backward );
我不知道你是否必須用它包圍它
this->anim->pause();
//[...]
this->anim->resume();
也許你必須稍微體驗一下。
另外,也許您必須跟蹤
1.)您是否已經開始向前和向后啟動影片,因為沒有啟動兩次甚至更頻繁,例如使用列舉來保護成員的安全狀態:
enum class eState { Stopped, Forward, Backward };
2.) 測驗影片是否仍在運行或已經完成,以便最終在向前或向后方向開始一個新影片,例如測驗
this->anim->currentTime() < this->anim->totalDuration();
// or just query the state
this->anim->state() == QAbstractAnimation::Stopped;
我希望我能幫助你解決你的問題。
編輯我的觀點 1.) 您還可以通過測驗使用影片類的方法來解決:
this->anim->direction(); // and...
this->anim->state();
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/513273.html
標籤:C qt
