Qt's floating ball menu

ten to eight

Qt's floating ball menu

Table of contents

Original link: Qt's floating ball menu

I. Overview

Recently, I want to make a cool floating menu. Considering the expansion and beauty of the menu, I consider learning Qt's animation system and state machine content. I opened the sample tutorial of QtCreator and browsed it. I found that the programs and programs in the tutorial are  2D Painting helpful  Animated Tiles . , as shown in the figure below, these two demos describe how to make an unfolding animation, interested students can also refer directly to

With these two demos, we can start to write our own programs.

2. Effect display

The following two pictures are the renderings of the author's two invalid floating menus, showing that the code in Figure 1 has been uploaded to CSDN, and can be downloaded without credits. The code in Figure 2 is not open source for the time being, and friends in need can consult further

Basic circular menu function, the code has been uploaded to CSDN -  Qt invalid PC-side circular menu, floating ball menu, expansion animation

Advanced floating ball menu, support secondary menu opening

3. Realize the code

The implementation file is relatively simple. There are only header files and implementation files. Here we mainly release the header files, and then explain the implementation ideas. The specific implementation details can be learned by downloading the source code.

1. Menu items

PopRingItem is a menu expansion item, which can realize the same function as a normal menu by binding an external QAction

class PopRingItem : public QLabel
{
	Q_OBJECT

public:
	PopRingItem(QWidget *parent = 0);
	~PopRingItem();

	void SetRadius(int radius);
	int GetRadius() const;

	void BindAction(QAction * action);

signals:
	void MouseEvent(bool);

protected:
	virtual void enterEvent(QEvent * event) override;
	virtual void leaveEvent(QEvent * event) override;

	virtual void paintEvent(QPaintEvent * event) override;

protected:
	int m_iRadius = 50;
	QAction * m_actAction = nullptr;
};

2. Suspended ball

The floating ball is the menu entry, inherited from the menu item, and has similar functions to the menu item

class QVariantAnimation;
class QPropertyAnimation;
class PopRingMenu : public PopRingItem
{
	Q_OBJECT

public:
	PopRingMenu(QWidget *parent = 0);
	~PopRingMenu();

signals:
	void DoubleClicked();

public:
	void SetActions(const QVector<QAction *> & acts);
	void SetIcons(const QVector<QString> & icons);

	void SetAnimationEnabled(bool enabled);
	bool IsAnimationEnabled() const;

	void SetSlowlyFade(bool enabled);
	bool IsSlowlyFade() const;

	void SetDistanced(int distance);
	int GetDistanced() const;

	void SetStartAngle(int angle);
	int GetStartAngle() const;

	void SetStepAngle(int angle);
	int GetStepAngle() const;

	void SetNormalMenuSize(int size);
	int GetNormalMenuSize() const;
	void SetNormalItemSize(int size);
	int GetNormalItemSize() const;

protected:
	virtual void enterEvent(QEvent * event) override;
	virtual void leaveEvent(QEvent * event) override;
	virtual void mouseDoubleClickEvent(QMouseEvent * event) override;

	virtual void timerEvent(QTimerEvent * event) override;
	virtual bool event(QEvent * event) override;

private slots:
	void OnMouseEvent(bool);

private:
	void UpdateActions(int msecond);

	void ExpandMenu();
	void CollapseMenu();

	void SlowlyFade();
	void QuicklyLighter();

	bool IsUnderMouse() const;

	void TryCollapseMenu();
	void KillHideTimer();

private:
	int m_iDistance = 70;
	int m_iStartAngle = 0;
	int m_iStepAngle = 60;

	int m_iMenuSize = 70;
	int m_iItemSize = 60;

	int m_iTimerID = -1;

	QPropertyAnimation * m_pOpacityAnimation = nullptr;
	QVariantAnimation * m_pItemAnimation = nullptr;
	QVector<PopRingItem *> m_items;
};

3. Key points

Initialize the animation object, specify the animation duration and animation start and end values

The animation specific implementation function is not UpdateAction, and calculate the position and size of the menu item at the current animation moment according to the proportion of the current animation progress value in the animation start value and end value

m_pItemAnimation = new QVariantAnimation(this);

m_pItemAnimation->setEasingCurve(QEasingCurve::InCubic);
m_pItemAnimation->setStartValue(ShowMenuStartValue);
m_pItemAnimation->setEndValue(ShowMenuEndValue);
m_pItemAnimation->setDuration(ShowMenuDuration);

connect(m_pItemAnimation, &QVariantAnimation::valueChanged, this, [this](const QVariant & v){
	UpdateActions(v.toInt());
});

When the mouse enters the floating ball, perform the expansion animation

void PopRingMenu::ExpandMenu()
{
	if (m_pItemAnimation)
	{
		if (m_pItemAnimation->state() != QAbstractAnimation::Running
			&& m_pItemAnimation->currentValue().toInt() != ShowMenuEndValue)
		{
			m_pItemAnimation->setDirection(QVariantAnimation::Forward);
			m_pItemAnimation->start();
		}
	}
	else
	{
		UpdateActions(ShowMenuEndValue);
	}

	KillHideTimer();
	QuicklyLighter();
}
  1. When the mouse leaves the floating ball, execute the retract animation, which is opposite to the unfold animation
  2. There is a detail point when retracting the animation, that is, when the mouse hovers on the menu item, it cannot be retracted
void PopRingMenu::CollapseMenu()
{
	if (false == IsUnderMouse())
	{
		if (m_pItemAnimation)
		{
			m_pItemAnimation->setDirection(QVariantAnimation::Backward);
			m_pItemAnimation->start();
		}
		else
		{
			UpdateActions(ShowMenuStartValue);
		}

		KillHideTimer();
		SlowlyFade();
	}
}

Expand and collapse animation implementation details, specify the number of frames according to the animation, scale and move menu items proportionally

void PopRingMenu::UpdateActions(int msecond)
{
	int curDistance = msecond * m_iDistance / ShowMenuEndValue;
	for (int i = 0; i < m_items.size(); ++i)
	{
		PopRingItem * item = m_items.at(i);
		
		double radians = qDegreesToRadians(m_iStepAngle * i * 1.0 + m_iStartAngle);
		int offx = curDistance * qCos(radians);
		int offy = curDistance * qSin(radians);
		item->move(pos() + QPoint(offx, offy));

		int curSize = msecond * m_iItemSize / ShowMenuEndValue;
		item->SetRadius(curSize);

		item->setVisible(ShowMenuStartValue != msecond);
	};

	::SetWindowPos(HWND(winId()), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}

When the floating ball is not activated for a specified time, it will fade out to reduce the visual impact on the user

void PopRingMenu::SetSlowlyFade(bool enabled)
{
	if (enabled)
	{
		if (nullptr == m_pOpacityAnimation)
		{
			m_pOpacityAnimation = new QPropertyAnimation(this, "opacity");
			m_pOpacityAnimation->setEasingCurve(QEasingCurve::OutCubic);
			m_pOpacityAnimation->setStartValue(SlowlyStartValue);
			m_pOpacityAnimation->setEndValue(SlowLyEndValue);
			m_pOpacityAnimation->setDuration(SlowlyFadeDuration);
		}
	}
	else
	{

		if (m_pOpacityAnimation)
		{
			delete m_pOpacityAnimation;
			m_pOpacityAnimation = nullptr;
		}
	}
}

4. Related Articles

  1. Qt menu item customization
  2. Qt  's QAbstractItemView right-click menu
  3. Qt popup menu shadow
  4. Qt's custom QLineEdit right-click menu
  5. Qt's stock component - self-selected stock - the list can be dragged and dropped, and the right-click menu is commonly used

Excellent articles worth a look:

  1. Financial Associated Press - Products
  2. Glodon- Products
  3. Qt custom control list
  4. Awesome Qt library

If you think the article is good, you may wish to give a reward, writing is not easy, thank you for your support. Your support is my greatest motivation, thank you! ! !
 


Very important -- reprint statement

  1. The articles on this site have no special instructions, all are original and copyrighted, please use the link when reprinting, and give the source of the original text. At the same time, write the original author: morning ten night eight  or  Twowords

  2. If you want to reprint, please reprint the original text. If you modify this article when reprinting, please inform in advance. It is forbidden to modify this article to benefit the reprinter when reprinting.


Nobody in the struggle. . .

Categories:  qt project cases  ,  qt classic articles  ,  qt learning cases  ,  custom controls

Guess you like

Origin blog.csdn.net/qq_30392343/article/details/127582384