视口和窗口的转换

本文详细解释了QPainter中的视口与窗口坐标系统,展示了如何在不同坐标系间转换,并通过实例说明了视口设置对绘图的影响。重点在于理解默认坐标系、逻辑与物理坐标的关系,以及如何调整视口和窗口范围以实现预期效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、基础概念:

在QPainter的默认坐标系中,点(0,0)位于绘图设备的左上角,x坐标向右增长,y坐标向下增长。默认坐标系的每个像素占1 x 1大小的区域。

理论上,像素的中心取决于半像素坐标。例如,窗口部件的左上角像素覆盖了点(0,0)到点(1,1)的区域,它的中心在(0.5,0.5)位置。

视口和窗口密不可分。视口是物理坐标系下指定的任意矩形。窗口和视口是同一个矩形,但是窗口是逻辑坐标系,窗口可以定义视口的逻辑坐标范围

默认情况下,视口和窗口都设置设备的矩形。例如,如果设备是300 x 300的矩形,视口和窗口都是左上角为(0,0)的300 x 300 的相同矩形,此时逻辑坐标系和物理坐标系一致。

例如在逻辑坐标系下绘制一个左上角为(0,0)的100 x 100 的矩形,如下所示:

Widget::Widget(QWidget *parent) 
	: QWidget(parent)
	, ui(new Ui::Widget)
{
	ui->setupUi(this);
	setPalette(QPalette(Qt::white));
	setAutoFillBackground(true);
	this->resize(300 , 300 ); // 设备坐标(物理坐标)
}
void Widget::paintEvent(QPaintEvent *event)
{
	Q_UNUSED(event);
	QPainter painter(this);

	//设置画笔
	QPen pen;
	pen.setWidthF(1); //线宽
	pen.setStyle(Qt::SolidLine);//线的类型,实线、虚线等
	pen.setCapStyle(Qt::FlatCap);//线端点样式
	pen.setJoinStyle(Qt::BevelJoin);//线的连接点样式
	pen.setColor(Qt::gray); //划线颜色

	pen.setColor(Qt::red); //划线颜色
	painter.setPen(pen);

	painter.drawText(QPoint(width() / 2, 10), QString("widget size (%1, %2)")
		.arg(width()).arg(height()));

	pen.setColor(Qt::blue); //划线颜色
	painter.setPen(pen);
	painter.drawRect(0, 0, 100, 100);
}

 

 由上图可知,逻辑坐标系和物理坐标系一致的。

二、视口与窗口:

QPainter提供了视口(Viewport)和窗口(Window)两个坐标系,通过QPainter内部的坐标变换矩阵自动转换为绘图设备的物理坐标。

视口表示绘图设备(例如QImage, QPicture, QPixmap, QWidget等)的任意一个矩形区域的物理坐标,可以只选取物理坐标的一个矩形区域用于绘图。默认情况下,视口(Viewport)等于绘图设备的整个矩形区,属于物理坐标系

视口矩形区域通过painter.setViewport(rect)方法设置,然后通过通过painter.setWindow()方法设定这个矩形区域的范围,配合使用,否则会出现问题(下文会举例写到)。

举例:在窗体部件(绘图设备)里取一块矩形(具体见代码)作为视口,同时设置视口矩形区域的范围(-100, -100, 200, 200),即左上角为(-100,-100),右下角为(100,100)。通过QPainter绘制一个左上角为(0,0),边长为100的正方形,如下所示:

void Widget::paintEvent(QPaintEvent *event)
{
	Q_UNUSED(event);
	QPainter painter(this);

	//设置画笔
	QPen pen;
	pen.setWidthF(1); //线宽
	pen.setStyle(Qt::SolidLine);//线的类型,实线、虚线等
	pen.setCapStyle(Qt::FlatCap);//线端点样式
	pen.setJoinStyle(Qt::BevelJoin);//线的连接点样式
	pen.setColor(Qt::gray); //划线颜色
	painter.setRenderHint(QPainter::Antialiasing);

	pen.setColor(Qt::red); //划线颜色
	painter.setPen(pen);

	int W = width();
	int H = height();

	painter.drawText(QPoint(width() / 2 - 10, 10), QString("widget size (%1, %2)")
		.arg(W).arg(H));

	int side = qMin(W, H);//去长和宽的小值
	// viewport矩形区
	QRect rect((W - side) / 2 + 100, (H - side) / 2 + 100, side - 200, side - 200);
    // 在原有坐标系下,绘制出Viewport区域
	painter.drawRect(rect); 
	painter.drawText(QPoint(width()/2 - 50, 50), QString("rect size (%1, %2)")
		.arg(rect.width()).arg(rect.height()));

	painter.setViewport(rect);//设置 Viewport
	painter.setWindow(-100, -100, 200, 200); // 设置窗口范围,逻辑坐标

	// 绘制矩形中心十字线
	pen.setColor(Qt::gray);
	pen.setStyle(Qt::DashLine);
	painter.setPen(pen);
	painter.drawLine(QPoint(-100, 0), QPoint(100, 0));
	painter.drawLine(QPoint(0, -100), QPoint(0, 100));

	pen.setColor(Qt::blue); //划线颜色
	pen.setStyle(Qt::SolidLine);//线的类型,实线、虚线等
	painter.setPen(pen);
	painter.drawRect(0, 0, 100, 100);
}

在上述代码中,如果未设置painter.setWindow()方法,即没有设定视口矩形的范围,系统将默认把绘图设备的区域,与视口矩形进行绑定。如果绘图设备是矩形的话,绘制的蓝色矩形将是个矩形,如果把绘图设备区域拉宽的话,蓝色矩形将被收窄。坐标原点都是左上角

如果将painter.setWindow(-100, -100, 200, 200)的范围,改成(-200, -200, 400, 400),蓝色的矩形将缩小一倍。

、逻辑坐标向物理坐标的转换:

由上面的例子,可以总结出转换规律:

默认情况视口和窗口坐标一致;如果设置视口矩形,窗口也要保证矩形一致,但需要通过setWindow方法设置矩形的逻辑坐标范围。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值