在QPainter中,绘制图像使用逻辑坐标绘制,然后再转化为绘图设备的物理坐标。
- 窗口(window):表示逻辑坐标下的相同矩形
- 视口(viewport):表示物理坐标下的指定的一个任意矩形
默认情况:逻辑坐标和物理坐标是重合的。
setWindow() | 设置逻辑坐标 |
setViewPort() | 设置物理坐标 |
保存状态和返回状态:
save() | 保存当前的状态 |
restore() | 返回上一个状态 |
例子:
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QPen pen(Qt::black);
pen.setCapStyle(Qt::RoundCap);//笔帽的样式
pen.setJoinStyle(Qt::RoundJoin);//连接的样式
pen.setWidth(10);
painter.setBrush(Qt::black);
painter.setPen(pen);//设置笔
painter.save();//保存当前设置
painter.drawRect(0,0,100,100);
QPen pen1(Qt::cyan);
pen1.setCapStyle(Qt::FlatCap);//笔帽的样式
pen1.setJoinStyle(Qt::BevelJoin);//连接的样式
pen1.setWidth(10);
painter.setBrush(Qt::cyan);
painter.setPen(pen1);//设置笔
painter.drawRect(100,100,100,100);
painter.restore();//返回上一个设置
painter.drawRect(200,200,100,100);
}
窗口和视口的分析和使用:
初始窗口和视口的大小:
- 初始状态下:窗口和视口的大小相同,相当于窗口的大小
- 可以修改窗口大小(在构造函数中resize())
窗口的初始大小:
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(Qt::cyan);
painter.setBrush(Qt::blue);
qDebug()<<"视口的宽度="<<painter.viewport().width()<<"视口的高度="<<painter.viewport().height();
qDebug()<<"窗口的宽度="<<painter.window().width()<<"窗口的高度="<<painter.window().height();
}
修改窗口大小:
在构造函数中使用resize()函数
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
resize(400,400);
}
再次运行:
只修改视口
只修改视口时,相当于对绘制的图形进行缩放。
- setViewport() 的宽度和高度大于初始视口的宽度和深度,相当于放大
- setViewport() 的宽度和高度小于初始视口的宽度和深度,相当于缩小
放大或缩小倍数为:
- 宽度的倍数: 现视口宽度/初始视口宽度
- 高度的倍数: 现视口高度/初始视口高度
起始点为:setViewport() 设置的起始点,例如 setViewport(50,50,100,100)
- 把(0,0)位置放到 (50,50)上
当 setViewport()的起始坐标为(0,0)时
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
resize(400,400);
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(Qt::cyan);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
//改变视口
//缩小
painter.setViewport(0,0,200,200);
painter.drawRect(0,0,100,100);//绘制一个矩形
painter.drawLine(100,0,0,100);//绘制一个线段
painter.setViewport(50,50,200,200);
painter.drawRect(0,0,100,100);//绘制一个矩形
painter.drawLine(100,0,0,100);//绘制一个线段
}
只修改窗口
只修改窗口时,也是对窗口进行放大和缩小
- setWindow() 的宽度和高度小于初始窗口的宽度和深度,相当于放大
- setWindow() 的宽度和高度小于初始窗口的宽度和深度,相当于缩小
- 宽倍数的计算: 初始窗口宽度/现窗口宽度
- 高倍数的计算: 初始窗口高度/现窗口高度
当setWindow()的初始坐标不为(0,0)时位置的计算:
设setWindow(X,Y,M,N) 点位为Point(A,B)
- 宽: (A-X)*倍数
- 高:(B-Y)*倍数
当 setWindow()起始坐标未改变时:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
resize(400,400);
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(Qt::cyan);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
//改变窗口
//缩小
painter.setWindow(0,0,800,800);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
//放大
painter.setWindow(0,0,200,200);
painter.drawRect(0,0,150,150);//绘制一个矩形
painter.drawLine(150,0,0,150);//绘制一个线段
}
setWindow()的初始坐标不为(0,0)时
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
resize(400,400);
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(Qt::cyan);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
//改变窗口
painter.setWindow(50,50,100,100);
QPen pen(Qt::red);
pen.setWidth(2);
painter.setPen(pen);
painter.drawPoint(50,50);//绘制一个点
painter.drawPoint(75,75);//绘制一个点
painter.drawPoint(100,100);//绘制一个点
}
矩形的位置确定:
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
resize(400,400);
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(Qt::cyan);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
//改变窗口
painter.setWindow(50,50,100,100);
QPen pen(Qt::red);
pen.setWidth(2);
painter.setPen(pen);
painter.drawRect(0,0,100,100);
painter.drawRect(50,50,100,100);
}
窗口和视口的综合使用:
1.当窗口和视口相同时:根据窗口和视口的特性,显示窗口相当于没有改变。
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(Qt::cyan);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
//改变窗口和视口
//窗口和视口相同
painter.setWindow(0,0,100,100);
painter.setViewport(0,0,100,100);
//painter.setWindow(50,50,100,100);
//painter.setViewport(50,50,100,100);
painter.setPen(Qt::red);
painter.drawRect(0,0,100,100);//绘制一个矩形
painter.drawLine(100,0,0,100);//绘制一个线段
}
2.当窗口和视口不同时
坐标相同,宽高不同时
- 宽的倍数:视口宽/窗口宽
- 高的倍数:视口高/窗口高
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(Qt::cyan);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
//改变窗口
//窗口和视口不同
painter.setWindow(0,0,100,100);
painter.setViewport(0,0,50,50);
painter.setPen(Qt::red);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
}
坐标不同,宽高相同(坐标为正数的话)
- 修改窗口坐标,相当于往左上平移
- 修改视口坐标,相当于往右下平移
- 计算公式: X=窗口x-视口x Y=窗口y-视口y
- X大于0时往左平移,X小于0时往右平移
- Y大于0时往上平移,Y小于0时往下平移
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(Qt::cyan);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
//改变窗口
//窗口和视口不同
//改变视口坐标,相当于平移
painter.setWindow(0,0,100,100);
painter.setViewport(50,50,100,100);
painter.setPen(Qt::red);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setPen(Qt::cyan);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
//改变窗口
//窗口和视口不同
//修改窗口位置
painter.setWindow(50,50,100,100);
painter.setViewport(0,0,100,100);
painter.setPen(Qt::red);
painter.drawRect(0,0,200,200);//绘制一个矩形
painter.drawLine(200,0,0,200);//绘制一个线段
}
当窗口不是正方形时,修改窗口时,可能图形会发生变化
本该绘制一个正方型,但实际上绘制出来的时长方形
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
resize(400,300);//窗口大小为(400,300)
}
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setWindow(-50,-50,100,100);
painter.drawRect(0,0,25,25);//绘制一个正方形
}
通过改变视口来还原图形
int side = qMin(width(), height());//获取两个参数的最小值
int x=(width() - side)/2; //调整宽度
int y=(height() - side) /2;//调整高度
painter.setViewport(x, y, side, side);//设置视口
void Widget::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setWindow(-50,-50,100,100);
int side = qMin(width(), height());
painter.setViewport((width() - side)/2, (height() - side) /2, side, side);
painter.drawRect(0,0,25,25);
}