窗口-视口转换(详细)

在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);
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值