【Qt学习笔记】11.自定义控件 Customize the Widget

一、窗口绘制——基本方法

自定义窗口:

Qt里允许自定义窗口控件,使之满足特殊的要求:

1、可以修改其显示,自行绘制

2、可以呈现动态效果

3、可以添加事件,支持鼠标和键盘操作

自定义的控件可以直接在Qt Designer 中使用,可以直接加到父窗口里。

步骤:

1、新建一个类,继承于QWidget和QFrame,最好是继承于QFrame
2、重写以下函数 void CellMonitor::paintEvent( QPaintEvent* event )

3、使用这个类

CircleWidget::CircleWidget(QWidget *parent)
	: QFrame(parent)
{
}

CircleWidget::~CircleWidget()
{
}

void CircleWidget::paintEvent(QPaintEvent * event)
{
	QPainter painter(this);
	painter.setBrush(QBrush(QColor(0x00, 0xff, 0x00)));
	painter.drawEllipse(QPoint(100, 100), 100, 100);
}

在Qt Designer里使用:

自定义的Widget可以和原生控件一样,直接在Qt Designer里拖放布局。

1、拖放一个父类控件,如QFrame

2、Promote to ...具体化为子类控件,即可完成

二、窗口的绘制——几何图形的绘制

常用:

Line:直线

Rect:长方形(含正方形)

Ellipse:椭圆(含圆形)

其他:

Arc:圆弧

Chord:封闭圆弧

polygon:多边形

RGB颜色:

在绘图时经常要指定颜色,Qt里使用RGB颜色,即由Red、Green、Blue分量定义的颜色值。每个分量0 ~ 255

如:

QColor green(0, 0xFF, 0);

QColor white(0xFF, 0xFF, 0xFF);

QColor black(0, 0, 0);

QPen与QBrush:

在Qt中,有两种绘制参数

QPen:负责线条的颜色和风格

QBrush:负责填充的颜色和风格

比如说,当画一个圆时,由当前QPen来决定线条,由QBrush来决定填充(所围区域)

注意:

1、对于非闭合形状,如Line,是不填充的

2、要先设置好色彩 然后再画,不然画完才设置颜色显然是无意义的

常用的几个类型:

QPoint:描述了一个点的坐标

QSize:描述了宽度和高度

QRect:描述了一个矩形的坐标和大小

另外,QPointF、QRectF是对应的float版本

一般情况下,后绘制的窗口会覆盖先前绘制的窗口

三、窗口的绘制——动画的实现

图画的运动:

每秒钟重绘n次,对人眼来说,它看起来就是运动的

步骤:

1、创建一个定时器

2、调用QWidget::update(),通知界面重绘

注意:

update()函数只是通知界面重新绘制,会在事件循环中产生一个“绘制事件(paint event)”,在适合的时候才会重新绘制 (简单的说,就是生成了一个重绘信号,等待响应处理,而并不是立刻重绘)

四、窗口的绘制——文字的绘制

1、颜色:QPen

2、字体:QFont

字体包含以下参数:

family(字体):如 "Times" "宋体"

size(大小):如 10  16

weight(样式): 如 QFont:Normal, QFont::Bold QFont::Light 等......

italic(斜体):true false

3、位置与对齐

painter.drawText(0, 0, width, 40 ,//指定位置

Qt::AlignHCenter | Qt::AlignVCenter,    //指定对齐等属性

"hello world")

);

示例代码:

	QPainter painter(this);
	QFont font("Times", 20, QFont::Light, true);

	painter.setPen(QColor(0xFF, 0, 0));
	painter.setFont(font);
	painter.drawText(0, 0, width(), height(), Qt::AlignLeft | Qt::AlignTop, "Change World");

五、窗口的绘制——图片的绘制

Qt中使用QPixmap表示图片

图片的来源:

Qt里的图片有两种加载方式:

1、文件系统中的文件

使用绝对路径或相对路径来指定

2、资源中的文件

:/xxx/Resources/XX.jpg   (使用冒号开头)

绘制参数:

1、源矩形

可以绘制图像的全部,也可以只绘制其中一部分

QRect source(0, 0, img_width, img_height);    //源矩形

2、目标矩形

可以填充到全部窗口,也可以只填充到一部分

QRect target(0, 0, width/2, height/2);        //目标矩形

painter.drawPixmap(target, m_picture, source);    //绘制

注意事项:

QPixmap应该作为成员变量,只加载一次,这是因为:

1、加载成本很高(开销大)

2、也没有必要反复加载

六、鼠标的支持——基本概念

Qt中鼠标事件分为四种:

1、按下    Press

2、抬起    Release

3、移动    Move

4、双击    Double Click

用QMouseEventl类表示一个鼠标事件

x,y: 坐标

globalX, globalY: 全局坐标

button: 鼠标左键、右键、中间

鼠标事件继承与 QWidget,因此重写这4个事件的处理方法,就可以自定义控件支持鼠标操作

void mouseDoubleClickEvent( QMouseEvent* event );
void mouseMoveEvent( QMouseEvent* event );
void mousePressEvent( QMouseEvent* event );
void mouseReleaseEvent( QMouseEvent* event );

小练习:

写一个程序,当鼠标按下时,画出鼠标移动的轨迹,直到松开为止

按下时: m_pressedFlag = true;

移动时: 记录轨迹

松开时: m_pressedFlag = false;

效果如下:

实现代码:

class MyWidget : public QFrame
{
	Q_OBJECT

public:
	MyWidget(QWidget *parent);
	~MyWidget();
private:
	void paintEvent( QPaintEvent* event );

	//鼠标事件
	void mouseDoubleClickEvent(QMouseEvent *event);
	void mouseMoveEvent(QMouseEvent *event);
	void mousePressEvent(QMouseEvent *event);
	void mouseReleaseEvent(QMouseEvent *event);

private:
	bool m_pressedFlag;
	QVector<QPoint> m_points;		//存放轨迹的集合
};

MyWidget::MyWidget(QWidget *parent)
	: QFrame(parent)
	, m_pressedFlag(false)
{
	m_points.resize(1024);
}

MyWidget::~MyWidget()
{
}

void MyWidget::paintEvent(QPaintEvent* event)
{
	QPainter painter(this);
	int width = this->width();
	int height = this->height();

	//背景
	painter.setBrush(QColor(0, 0, 0));		//黑色
	painter.drawRect(0, 0, width, height);

	painter.setPen(QColor(255, 255, 255));

	for (size_t i = 0; i < m_points.size() - 1; ++i)	//遍历
	{
		QPoint& p1 = m_points[i];
		QPoint& p2 = m_points[i + 1];
		painter.drawLine(p1, p2);
	}
}

//忽略双击事件
void MyWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
	QWidget::mouseDoubleClickEvent(event);
}

void MyWidget::mouseMoveEvent(QMouseEvent *event)
{
	if (m_pressedFlag == true)
	{
		QPoint pos = event->pos();
		//显示轨迹
		m_points.push_back(pos);
		update();	//重绘
	}
}

//鼠标按下
void MyWidget::mousePressEvent(QMouseEvent *event)
{
	m_pressedFlag = true;
	m_points.clear();
}

//鼠标抬起
void MyWidget::mouseReleaseEvent(QMouseEvent *event)
{
	m_pressedFlag = false;
}

七、鼠标的支持——发射信号

事件与信号:

自定义控件的事件发生时,应该以信号的形式发送出去。

例如:对于一个按钮,当它被按下时(press, release),对外发射了一个clicked()信号

自定义信号的方式如下:

class XXX
{
signals:
    void SignalName( QPoint pos );
}

当事件发生时,

emit SignalName( pos );

通过emit操作将信号发射出去。

注意:emit并非C++的语法,是Qt里面自己加的概念

小练习:

区域截图:加载一张图片,选中一个区域,当鼠标松开后,发射一个信号

做出下面的效果:

代码:

class MyWidget : public QFrame
{
	Q_OBJECT

public:
	MyWidget(QWidget *parent);
	~MyWidget();

private:
	void paintEvent( QPaintEvent* event );

	//鼠标支持
	void mouseMoveEvent(QMouseEvent *event);
	void mousePressEvent(QMouseEvent *event);
	void mouseReleaseEvent(QMouseEvent *event);

private:
	bool m_pressedFlag;
	QPixmap m_picture;
	QPoint m_curPos;	//鼠标当前位置
	QPoint m_begin;
	QPoint m_end;
};

MyWidget::MyWidget(QWidget *parent)
	: QFrame(parent)
	,m_pressedFlag(false)
	,m_begin(QPoint(0, 0))
	,m_end(QPoint(0, 0))
{
	m_picture.load("./Resources/MyPic.jpg");		//开销大,写在构造函数中,只加载一次,而不是写在paintEvent中,每次显示
}

MyWidget::~MyWidget()
{
}

void MyWidget::paintEvent(QPaintEvent* event)
{
	QPainter painter(this);
	int width = this->width();
	int height = this->height();

	//显示背景图片
	painter.drawPixmap(0, 0, width, height, m_picture);

	//画出区域
	if (m_pressedFlag == true)
	{
		//画一个十字交叉线
		painter.setPen(QColor(255, 0, 0));	//红色的区域为十字交叉线
		painter.drawLine(QPoint(0, m_curPos.y()), QPoint(width, m_curPos.y()));	//水平
		painter.drawLine(QPoint(m_curPos.x(), 0), QPoint(m_curPos.x(), height));

		//画出选中的区域
		QRect selected(m_begin, m_end);
		painter.setPen(QColor(0, 0, 0));
		//painter.setBrush(QColor(100, 100, 100));
		painter.drawRect(selected);
	}
}

//鼠标移动
void MyWidget::mouseMoveEvent(QMouseEvent *event)
{
	if (m_pressedFlag = true)
	{
		m_curPos = event->pos();
		m_end = m_curPos;
		update();
	}
}

//鼠标按下
void MyWidget::mousePressEvent(QMouseEvent *event)
{
	m_pressedFlag = true;
	m_begin = event->pos();
	m_end = m_begin;

}

//鼠标抬起
void MyWidget::mouseReleaseEvent(QMouseEvent *event)
{
	m_pressedFlag = false;
}

————————————

尾巴

这一次东西蛮多的

时间: 2024-10-18 09:00:44

【Qt学习笔记】11.自定义控件 Customize the Widget的相关文章

Qt学习笔记-Widget布局管理

Qt学习笔记4-Widget布局管理 以<C++ GUI Programming with Qt 4, Second Edition>为参考 实例:查找对话框 包含三个文件,finddialog.h,finddialog.cpp及main.cpp. //finddialog.h代码 #ifndef FINDDIALOG_H#define FINDDIALOG_H #include <QDialog> class QCheckBox;class QLabel;class QLineE

【Qt学习笔记】2.窗体Widget && 屏幕坐标 && 布局

一.窗体 在Qt中,把窗体(口)叫做Widget. Widget可以是主窗体(口),也可以是依附在主窗体(口)上的各种控件,作为子窗体,这两种窗口,分别称作顶级窗口(top-level widget)和子窗口(sub widget). 顶级窗口:一个标准的窗口,带边框.标题栏.若干按钮.(独立) 子窗口:在窗口里面的窗口,例如:按钮.文本框等控件.(不独立,随着父窗口移动) 注意: 1.每个子窗口都有一个父窗口 2.子窗口里面可能包含了若干子窗口,是一层一层的关系. 3.顶级窗口也有父窗口:就是

qt学习笔记(五) QGraphicsPixmapItem与QGraphicsScene的编程实例 图标拖动渐变效果

应大家的要求,还是把完整的project文件贴出来,大家省点事:http://www.kuaipan.cn/file/id_48923272389086450.htm 先看看执行效果,我用的群创7寸屏,主机是mini2440,分辨率是800*480,程序写比較粗糙,但对刚開始学习的人还是有一点启示,大家一起进步. qt中提供了QGphicsView,QGraphicsScene,QGraphicsItem,QGraphicsPixmapItem是QGraphicsItem的子类 分辨创建它们的实

QT学习笔记—1

1.模态和非模态的区别:非模态可以同时操作两个窗口,模态的只能在顶层窗口关闭之后才能使用其他窗口 //同时显示出widget和dialog窗口,非模态     QDialog *dialog = new QDialog(this);     dialog->show(); //同时显示出widget和dialog窗口,模态     QDialog *dialog = new QDialog(this);     dialog->setModal(true);     dialog->sh

《C++ Primer Plus》学习笔记11

<C++ Primer Plus>学习笔记11 第17章 输入.输出和文件 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<

[Aaronyang] 写给自己的WPF4.5 笔记11[自定义控件-AyImageButton篇 1/4]

我的文章一定要对读者负责-否则不是好文章  ----       www.ayjs.net  aaronyang技术分享 文章导航: 介绍vs2013 WPF开发,属性代码相关技巧 实战AyImageButton 1.0细用慢讲,学会用户控件,依赖属性,属性回调事件 诞生AyImageButton 1.1 支持 控件简单写法,支持自定义AyImageButton写法,提供详细的API 效果图: AyImageButton记录 源码下载:http://pan.baidu.com/s/1eQlHly

sqlite学习笔记11:C语言中使用sqlite之删除记录

最后一节,这里记录下如何删除数据. 前面所有的代码都继承在这里了,在Ubuntu14.04和Mac10.9上亲测通过. #include <stdio.h> #include <stdlib.h> #include "sqlite/sqlite3.h" #define DB_NANE "sqlite/test.db" sqlite3 *db = NULL; char* sql = NULL; char *zErrMsg = NULL; con

【Qt学习笔记】13.拖放技术:Drag & Drop

1.接受拖放 Drag & Drop 是一个界面操作,用于在两个窗口间传递数据. Drag Source: 拖放源窗口 Drag Target: 拖放目标窗口 拖放操作: 1.在源窗口:选中目标,按下鼠标,移动,拖至目标窗口(Drag) 2.在目标窗口:取消鼠标,到指定位置,松开鼠标(Drop) (按下ESC取消操作) MIME: MIME(Multipurpose Internet Mail Extensions)被传递的数据以MIME格式传送,它是多组type-data数据:(type0,

lua学习笔记11:lua中的小技巧

lua中的小技巧,即基础lua语言本身的特种,进行一个些简化的操作 一 巧用or x = x or v 等价于: if not x then x = v end 如果x为nil或false,就给他赋值为 二 三元运算符实现 a and b or c 类似C语言: a ? b : c and 的运算由优先级高于or lua学习笔记11:lua中的小技巧,布布扣,bubuko.com