QPushButton定製化按鈕

在項目中經常遇到需要高度定製的QPushButton,互斥性的QPushButton菜單便是其中一例。老手就不用看了,沒啥技術含量,希望能給新手點思路吧。再複雜的控件,也可以通過這種思路去構造。

效果圖如下:

基本需求就是鼠標三態(normal,hover,press),佈局樣式就是圖片+文字。這種樣式的按鈕應用場景還是挺多的,比如tab頁,工具欄,小到單個按鈕的需求。

基本思路:單個按鈕封裝成控件,這個控件包含這個按鈕的類別,文字,以及圖片路徑的類信息成員。然後實現這個控件的mouseReleaseEvent,enterEvent, leaveEvent等。再提供一個setStyle接口,用於設置不同狀態下的樣式。最後再把這些單個控件放到佈局裏,或者說是上層封裝的一個控件(比如工具欄控件)。 上面的樣式我只用到了兩態,實現的也有複雜一些的,不過道理都是一樣的。上代碼吧。

NaviBtn.h

#include <QWidget>
class QLabel;

enum ENavi
{
	Navi_ClassRoom,
	Navi_Courseware,
};

struct NaviInfo
{
	ENavi type;
	QString name;
	QString imagePath;
};

class NaviBtn : public QWidget
{
	Q_OBJECT

public:
	NaviBtn(QWidget *parent, const NaviInfo &naviInfo);
	~NaviBtn();
	void setChecked(bool checked = true);
	ENavi getType() { return m_NaviInfo.type; }

protected:
	virtual void mouseReleaseEvent(QMouseEvent * event);
	void paintEvent(QPaintEvent *event);

private:
	void setStyle(bool checked = false);

signals:
	void sig_NaviBtnClick(ENavi type);

private:
	NaviInfo m_NaviInfo;
	QLabel* m_ImageLbl			= nullptr;
	QLabel* m_NameLbl			= nullptr;
	bool m_IsChecked			= false;
};

NaviBtn.cpp

NaviBtn::NaviBtn(QWidget *parent, const NaviInfo &naviInfo)
	: QWidget(parent),m_NaviInfo(naviInfo)
{
	setFixedSize(104, 104);
	setObjectName("NaviBtn");

	m_ImageLbl = new QLabel(this);
	m_ImageLbl->setFixedSize(48, 48);
	m_NameLbl = new QLabel(this);
	m_NameLbl->setText(m_NaviInfo.name);
	m_NameLbl->setObjectName("NaviBtnName");

	QVBoxLayout* layout = new QVBoxLayout(this);
	layout->setSpacing(0);
	layout->setContentsMargins(0, 14, 0, 0);
	layout->setAlignment(Qt::AlignHCenter|Qt::AlignTop);

	layout->addWidget(m_ImageLbl, 0, Qt::AlignHCenter);
	layout->addSpacing(4);
	layout->addWidget(m_NameLbl, 0, Qt::AlignHCenter);
	layout->addStretch();

	setStyle(m_NaviInfo.type == Navi_ClassRoom);
}

NaviBtn::~NaviBtn()
{

}

void NaviBtn::mouseReleaseEvent(QMouseEvent * event)
{
	m_IsChecked = true;
	setStyle(true);
	emit sig_NaviBtnClick(m_NaviInfo.type);
}

void NaviBtn::setChecked(bool checked)
{
	m_IsChecked = checked;
	setStyle(checked);
}

void NaviBtn::setStyle(bool checked)
{
	QString imageStyle;
	if (checked)
	{
		setProperty("isCheck", true);
		m_NameLbl->setProperty("isCheck", true);
		imageStyle = QString("background-image:url(:/common/%1_check)").arg(m_NaviInfo.imagePath);
	}
	else
	{
		setProperty("isCheck", false);
		m_NameLbl->setProperty("isCheck", false);
		imageStyle = QString("background-image:url(:/common/%1)").arg(m_NaviInfo.imagePath);
	}
	style()->polish(this);
	m_NameLbl->style()->polish(m_NameLbl);
	m_ImageLbl->setStyleSheet(imageStyle);
}

void NaviBtn::paintEvent(QPaintEvent *event)
{
	QStyleOption opt;
	opt.init(this);
	QPainter p(this);
	style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

對應的qss樣式如下:

QWidget#NaviBtn
{
    border-radius:8px;
    background-color:transparent;
}

QWidget#NaviBtn[isCheck = "true"]
{
    background-color:rgba(0,0,0,0.06);
}

QLabel#NaviBtnName
{
    font-size:18px;
    color:rgba(0,0,0,0.6);
    font-weight:400;
    background-color:transparent;
}

QLabel#NaviBtnName[isCheck = "true"]
{
    color:#FF6000;
}

是不是很簡單呢~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章