Qt 自定义Widget组件

在某些时候需要设计特殊的界面组件,而在UI设计器的组件面板里没有合适的组件,这时候就需要设计自定义的界面组件。

所有的界面组件的基类是QWidget,要设计自定义的界面组件,可以从QWidget继承一个自定义的类,重定义它的paintEvent()事件,用Qt的绘图功能绘制组件外观,并实现需要的功能。

例如我们需要设计一个电池电量显示的组件,如下图所示。

Qt 自定义Widget组件_第1张图片   

1. 设计一个从QWidget继承的QmyBattery类。

类QmyBattery.h文件的完整代码如下

#pragma once

#include 
#include 

class QmyBattery : public QWidget
{
	Q_OBJECT
private:
	QColor mColorBack = Qt::white;		//背景颜色
	QColor mColorBorder = Qt::black;	//电池边框颜色
	QColor mColorPower = Qt::green;		//电池柱颜色
	QColor mColorWarning = Qt::red;		//电量短缺时的颜色
	int mPowerLevel = 60;				//电量0-100
	int mWarnLevel = 20;				//电量低警示阈值
protected:
	void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
public:
	explicit QmyBattery(QWidget * parent = 0);
	void setPowerLevel(int pow);		//设置当前电量
	int powerLevel();
	void setWarnLevel(int warn);				//设置电量低阈值
	int warnLevel();
	QSize sizeHint();					//缺省大小
signals:
	void powerLevelChanged(int);
};

下面是QmyBattery类的实现代码,主要是paintEvent()事件函数的绘制功能。

void QmyBattery::paintEvent(QPaintEvent *event)
{
	//界面组件的绘制
	Q_UNUSED(event);

	QPainter painter(this);
	QRect rect(0, 0, width(), height());
	painter.setViewport(rect);
	painter.setWindow(0, 0, 140, 50);	//设置窗口大小,逻辑坐标
	painter.setRenderHint(QPainter::Antialiasing);
	painter.setRenderHint(QPainter::TextAntialiasing);

	//绘制电池边框
	QPen pen;
	pen.setWidth(2);
	pen.setColor(mColorBorder);
	pen.setStyle(Qt::SolidLine);
	pen.setCapStyle(Qt::FlatCap);
	pen.setJoinStyle(Qt::BevelJoin);
	painter.setPen(pen);

	QBrush brush;
	brush.setColor(mColorBack);
	brush.setStyle(Qt::SolidPattern);
	painter.setBrush(brush);

	rect.setRect(1, 1, 129, 48);
	painter.drawRect(rect);		//绘制电池边框
	brush.setColor(mColorBorder);
	painter.setBrush(brush);
	rect.setRect(130, 15, 10, 20);
	painter.drawRect(rect);		//画电池正极头

	//画电池柱
	if (mPowerLevel > mWarnLevel)
	{
		//正常颜色电量柱
		brush.setColor(mColorPower);
		pen.setColor(mColorPower);
	}
	else
	{
		//电量低电量柱
		brush.setColor(mColorWarning);
		pen.setColor(mColorWarning);
	}

	painter.setBrush(brush);
	painter.setPen(pen);
	if (mPowerLevel > 0)
	{
		rect.setRect(5, 5, mPowerLevel, 40);
		painter.drawRect(rect);		//画电池柱
	}

	//绘制电量百分比文字
	QFontMetrics textSize(this->font());
	QString powStr = QString::asprintf("%d%%", mPowerLevel);
	QRect textRect = textSize.boundingRect(powStr);		//得到字符串的Rect
	painter.setFont(this->font());
	pen.setColor(mColorBorder);
	painter.setPen(pen);
	painter.drawText(55 - textRect.width() / 2, 23 + textRect.height() / 2, powStr);
}

QmyBattery::QmyBattery(QWidget * parent /*= 0*/):QWidget(parent)
{
}

void QmyBattery::setPowerLevel(int pow)
{
	mPowerLevel = pow;
	emit powerLevelChanged(pow);
	repaint();
}

int QmyBattery::powerLevel()
{
	return mPowerLevel;
}

void QmyBattery::setWarnLevel(int warn)
{
	mWarnLevel = warn;
}

int QmyBattery::warnLevel()
{
	return mWarnLevel;
}

QSize QmyBattery::sizeHint()
{
	int H = this->height();
	int W = this->width();
	QSize size(W, H);
	return size;
}

2. 自定义Widget组件的使用

实现了QmyBattery类之后,如果是用代码创建QmyBattery类对象,它的使用和一般的组件类是一样的;若是在UI设计器中使用QmyBattery,则要用提升法。

先在窗体上放置一个QWidget类组件,然后右击,点击“提升为...”菜单,出现如下对话框。

Qt 自定义Widget组件_第2张图片

在提升的类名称处填写刚刚创建的类名QmyBattery,头文件会自动生成,这是点击“添加”按钮,再点击“提升”,此时QWidget组件提升为QmyBattery类。右侧对象查看器可以看到类名的变化。

在主窗口放置一个QSlider组件和QLabel组件,当滑动标尺改变数值时,设置battery当前的电量值,其valueChanged()信号的槽函数如下。

void MainWindow::on_slider_valueChanged(int value)
{
	ui.battery->setPowerLevel(value);
	QString str = QString("当前电量: ") + QString::asprintf("%d %", value);
	ui.label->setText(str);
}

编译运行后效果如下图所示。

Qt 自定义Widget组件_第3张图片     Qt 自定义Widget组件_第4张图片

你可能感兴趣的:(Qt)