QPushButton定制化按钮

在项目中经常遇到需要高度定制的QPushButton,互斥性的QPushButton菜单便是其中一例。老手就不用看了,没啥技术含量,希望能给新手点思路吧。再复杂的控件,也可以通过这种思路去构造。

效果图如下:

QPushButton定制化按钮_第1张图片

基本需求就是鼠标三态(normal,hover,press),布局样式就是图片+文字。这种样式的按钮应用场景还是挺多的,比如tab页,工具栏,小到单个按钮的需求。

基本思路:单个按钮封装成控件,这个控件包含这个按钮的类别,文字,以及图片路径的类信息成员。然后实现这个控件的mouseReleaseEvent,enterEvent, leaveEvent等。再提供一个setStyle接口,用于设置不同状态下的样式。最后再把这些单个控件放到布局里,或者说是上层封装的一个控件(比如工具栏控件)。 上面的样式我只用到了两态,实现的也有复杂一些的,不过道理都是一样的。上代码吧。

NaviBtn.h

#include 
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;
}

是不是很简单呢~

你可能感兴趣的:(Qt控件样式专栏)