窗口-视口转换(详细)

news2024/7/4 5:38:48

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

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/25958.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

中国互联网大会天翼云展区大揭秘!

11月15日&#xff0c;由工业和信息化部、深圳市人民政府主办&#xff0c;中国互联网协会、广东省通信管理局、深圳市工业和信息化局等单位承办的2022&#xff08;第二十一届&#xff09;中国互联网大会在深圳开幕。本届大会以“发展数字经济 促进数字文明”为主题&#xff0c;聚…

单商户商城系统功能拆解34—应用中心—分销应用

单商户商城系统&#xff0c;也称为B2C自营电商模式单店商城系统。可以快速帮助个人、机构和企业搭建自己的私域交易线上商城。 单商户商城系统完美契合私域流量变现闭环交易使用。通常拥有丰富的营销玩法&#xff0c;例如拼团&#xff0c;秒杀&#xff0c;砍价&#xff0c;包邮…

在IDEA中搭建Spring5.2.x版本源码(~附带完整过程和图示~)

1.开发环境 JDK8IntelliJ IDEA 2019.1.4 gradle 5.6.4git 2.33.0 2.操作步骤 下载并安装git 进入https://git-scm.com/downloads&#xff0c;下载对应操作系统的git版本一直点击next安装即可记得配置环境变量 获取Spring源码 使用clone的方式将源码拉取到本地&#xff0c;方便…

Java递归查询树形结构(详解)

一.数据准备 数据库表结构如下所示&#xff0c; INSERT INTO jg_user.com_type(type_id, parent_id, type_name) VALUES (1, 0, 合伙企业); INSERT INTO jg_user.com_type(type_id, parent_id, type_name) VALUES (2, 0, 有限公司); INSERT INTO jg_user.com_type(type_id, p…

力扣(LeetCode)878. 第 N 个神奇数字(C++)

二分查找数论 数论知识——辗转相除法、容斥原理。 辗转相除求最大公约数&#xff0c;两数相乘除以最大公约数&#xff0c;就是最小公倍数。 容斥原理求最多不重复元素&#xff0c;最大不重复面积。 <小学数奥> 从数据范围里&#xff0c;用容斥原理找 a/ba/ba/b 的倍数个…

Pytorch 下 TensorboardX 使用

这里引用一下在其他地方看到的一些话&#xff1a; tensorboard做为Tensorflow中强大的可视化工具&#xff0c;已经被普遍使用。 但针对其余框架&#xff0c;例如Pytorch&#xff0c;以前一直没有这么好的可视化工具可用&#xff0c;PyTorch框架自己的可视化工具是Visdom&…

实验九 数据微积分与方程数值求解(matlab)

实验九 数据微积分与方程数值求解 1.1实验目的 1.2实验内容 1.3流程图 1.4程序清单 1.5运行结果及分析 1.6实验的收获与体会 1.1实验目的 1&#xff0c;掌握求数值导数和数值积分的方法&#xff1b; 2&#xff0c;掌握代数方程数组求解的方法&#xff1b; 3&a…

【Mysql】Centos 7.6安装Mysql8

这里centos为阿里云默认镜像。 一、卸载历史历史版本 1、检查是否有服务启动 # service mysqld status 2、停止mysql服务 # service mysqld stop 3、查看mysql历史安装组件 # rpm -qa|grep mysqlmysql-libs-5.1.71-1.el6.x86_64 4、卸载组件 # rpm -e --nodeps mysql…

2022世界VR产业大会圆满收官,酷雷曼惊艳亮相!

11月14日&#xff0c;由工业和信息化部、江西省人民政府联合主办的全球VR领域规模最大、规格最高、影响最广的年度盛会——2022世界VR产业大会在江西南昌圆满落下帷幕。 本次大会得到了党中央、国务院的高度重视&#xff0c;国务委员王勇出席大会开幕式并讲话&#xff1b;大会邀…

【转】DNS隧道检测特征

原文链接&#xff1a;DNS隧道检测特征总结 - 知乎 一、摘要 企业内网环境中&#xff0c;DNS协议是必不可少的网络通信协议之一&#xff0c;为了访问互联网和内网资源&#xff0c;DNS提供域名解析服务&#xff0c;将域名和IP地址进行转换。网络设备和边界防护设备在一般的情况…

C++:内存管理:C++内存管理详解

C语言内存管理是指&#xff1a;对系统的分配、创建、使用这一系列操作。在内存管理中&#xff0c;由于是操作系统内存&#xff0c;使用不当会造成很麻烦的后果。本文将从系统内存的分配、创建出发&#xff0c;并且结合例子来说明内存管理不当会造成的结果以及解决方案。 一&am…

【Spring】Spring AOP的实现原理

目录 什么是AOP AOP的作用 AOP的优点 AOP框架 Spring AOP AspectJ 术语 1.Target ——目标类 2.Joinpoint ——连接点 3.Pointcut——切入点 4.Advice——通知/增强 5.Weaving——植入 6.Proxy——代理类 7.Aspect——切面 底层逻辑 开发流程 1.导入依…

八、手把手教你搭建SpringCloudAlibaba之Sentinel服务降级之慢调用

SpringCloud Alibaba全集文章目录&#xff1a; 零、手把手教你搭建SpringCloudAlibaba项目 一、手把手教你搭建SpringCloud Alibaba之生产者与消费者 二、手把手教你搭建SpringCloudAlibaba之Nacos服务注册中心 三、手把手教你搭建SpringCloudAlibaba之Nacos服务配置中心 …

贪心算法应用

1. 算法思想 贪心算法一般分为如下四步&#xff1a; 将问题分解为若干个子问题找出适合的贪心策略求解每一个子问题的最优解将局部最优解堆叠成全局最优解 即选择每一阶段的局部最优&#xff0c;从而达到全局最优。 2. 最大自序和 题目描述 题目链接 给你一个整数数组 n…

用Servlet 编写hello world

第一次接触 Servlet&#xff0c;使用 Servlet 编写代码并配合 Tomcat 在浏览器中展示代码效果&#xff0c;也算是自己这么长时间学习java的一次飞升吧。 本文总结了六步使用 Servlet 编写 helloworld步骤&#xff0c;希望给初学Servlet的同学一些帮助。 0、准备工作 1&#xff…

Python 随机函数random详解

介绍这7个随机数的方法应用&#xff1a; 1、random.random&#xff08;&#xff09;查看源码 说明&#xff1a;用于生成一个0到1的随机符点数: 0 < x < 1.0 import random for i in range(10):print(random.random()) 2、random.uniform&#xff08;&#xff09;查看源码…

深度学习(14)—— 关于Tensorboard

深度学习&#xff08;14&#xff09;—— 关于Tensorboard 文章目录深度学习&#xff08;14&#xff09;—— 关于Tensorboard前言1. “一参数一图”2.“多参数一图”3. “一栏一图”4. “一栏多图”在模型训练过程中loss和acc都会发生变化&#xff0c;常常需要记录这些值&…

Spring Security(2)

您好&#xff0c;我是湘王&#xff0c;这是我的CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 前面已经把需要的环境准备好了&#xff0c;包括数据库和SQL语句&#xff0c;现在再来写代码。至于安装MySQL什么的就跳过去了&#xff0c;娘度子里面一大把。 先…

保护Excel表格的4种常用方法

今天来说说&#xff0c;根据不同需求&#xff0c;我们可以给Excel表格设置保护的4种常用方法&#xff0c;记得保存收藏&#xff0c;总有一个适合你。 方法一&#xff1a; 如果不想Excel表格被他人随意打开&#xff0c;可以设置“打开密码”&#xff0c;这样只有输入设置的密码…

OpenSergo 流量路由:从场景到标准化的探索

流量路由&#xff0c;顾名思义就是将具有某些属性特征的流量&#xff0c;路由到指定的目标。流量路由是流量治理中重要的一环&#xff0c;多个路由如同流水线一样&#xff0c;形成一条路由链&#xff0c;从所有的地址表中筛选出最终目的地址集合&#xff0c;再通过负载均衡策略…