python编程使用PyQt制作预览窗口游戏中的小地图
作者:在逆境中蜕变 发布时间:2023-12-29 09:54:24
写作思路
1、简述实现原理
2、部分代码解析
3、位置同步解析(①上下两屏位置同步②编辑屏位置保持不变)
效果图如下:
版本1:
这就是我们常见的预览窗口,上面预览窗口移动/缩放小方框都会导致下面的编辑界面位置发生变化,同理,下面的编辑界面的移动/缩放也会导致上面的小方框变化,并且上面预览图是编辑窗口的同比例缩放
版本2:
在版本1的基础上,加入了点的删除和增加,并对画布进行了扩展,同时保持编辑界面的画面位置不变
1、简述实现原理
首先最重要的,要知道我们这些是用QGraphicsView、QGraphicsScene、QGraphicsRectItem 这三个基类实现的
实现方法如下:
①QGraphicsScene.render渲染编辑窗口获得image,将image按照预览窗口的比例进行缩放并放入overView
②创建一个矩形框,框是按照编辑器窗口和image的比例进行绘制的
③拖动或者缩放预览窗口的时候,编辑窗口按照同样的比例移动缩放,拖动或者缩放预览窗口的时候同理
2、部分代码解析
①方框的完整代码
from PyQt5.QtCore import Qt, QRectF
from PyQt5.QtGui import QBrush, QPainterPath, QPainter, QColor, QPen
from PyQt5.QtWidgets import QGraphicsRectItem, QGraphicsItem
class GraphicsRectItem(QGraphicsRectItem):
def __init__(self, scene, *args):
super().__init__(*args)
self.scene = scene
self.setFlag(QGraphicsItem.ItemIsMovable, True)
self.setFlag(QGraphicsItem.ItemIsSelectable, True)
self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True)
self.setFlag(QGraphicsItem.ItemIsFocusable, True)
def shape(self):
path = QPainterPath()
path.addRect(self.rect())
return path
def paint(self, painter, option, widget=None):
# 框选出来的方形
painter.setBrush(QBrush(QColor(0, 0, 0, 0)))
painter.setPen(QPen(QColor(0, 0, 0), 0.1, Qt.SolidLine))
painter.drawRect(self.rect())
x = self.rect().x()
y = self.rect().y()
width = self.rect().width()
height = self.rect().height()
otherColor = QColor(150, 150, 150, 50)
painter.setBrush(QBrush(otherColor))
# 下面这部分代码是使得小方框以外的地方多一层蒙皮
painter.setPen(QPen(QColor(0, 0, 0, 0), 1.0, Qt.SolidLine))
painter.drawRect(QRectF(x-10000, y, 20000+width, -20000+height)) #上
painter.drawRect(QRectF(x-10000, y+height, 20000+width, 20000+height)) #下
painter.drawRect(QRectF(x, y, -20000, height)) #左
painter.drawRect(QRectF(x+width, y, 20000, height)) #右
painter.setRenderHint(QPainter.Antialiasing)
painter.setBrush(QBrush(QColor(255, 0, 0, 255)))
painter.setPen(QPen(QColor(0, 0, 0, 255), 1.0, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
这就是前面提到的 “item” 《scene view item的使用》,QGraphicsRectItem 也是继承自QGraphicsItem的,这里的方框就是我们要加到OverView界面中的那个定位方框
②编辑界面
class GraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super(GraphicsWindow, self).__init__(parent)
......
self.scene = ViewPortGraphScene(self)
self.setScene(self.scene)
......
self.setSceneRect(-1 << 30, -1 << 30, 1 << 31, 1 << 31)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
def addPoint(self, x, y):
self.scene.addEllipse(x, y, 16, 16, QPen(QColor(Qt.red)), QBrush(QColor(Qt.red)))
def mousePressEvent(self, mouseEvent):
......
if mouseEvent.button() == Qt.LeftButton:
if isinstance(self.itemAt(mouseEvent.pos()), QGraphicsEllipseItem):
self.scene.removeItem(self.itemAt(mouseEvent.pos()))
self.parent.changeView()
......
super(GraphicsWindow, self).mousePressEvent(mouseEvent)
class ViewPortGraphScene(QGraphicsScene):
def __init__(self, parent=None):
super(ViewPortGraphScene, self).__init__(parent)
......
def drawBackground(self, painter, rect):
# 自己去画格子吧 hhh
熟悉的操作:
1、创建scene
2、把scene放到view
3、把item放到scene,其中这里的item是点也就是QGraphicsEllipseItem,也是继承自QGraphicsRectItem
使屏幕可以拖动: self.setSceneRect(-1 << 30, -1 << 30, 1 << 31, 1 << 31),因为scene很大,在view里面装不下,所以就可以拖动啦~
**添加点:**如上的addPoint方法
**删除点:**如上的mousePressEvent方法,其中self.itemAt(mouseEvent.pos())可以获取当前鼠标位置是什么东西
③预览窗口
class OverViewGraphicsWindow(QGraphicsView):
def __init__(self, parent=None):
super(OverViewGraphicsWindow, self).__init__(parent)
......
self.scene = OverViewGraphScene(self)
self.item = GraphicsRectItem(self.scene, 0, 0, 50, 25)
self.scene.addItem(self.item)
......
......
class OverViewGraphScene(QGraphicsScene):
def __init__(self, parent=None):
super(OverViewGraphScene, self).__init__(parent)
同样的套路:
1、创建scene
2、把scene放到view
3、把item放到scene,其中这里的item是点也就是QGraphicsRectItem,继承自QGraphicsRectItem
3、位置同步解析
①上下两屏位置同步、编辑屏位置保持不变
1、两个pyqtSignal 分别去响应上下两个屏幕的移动和缩放
2、scene的的左上角到当前屏幕中心的长宽来定位(主要用到scene.itemsBoundingRect()、view.mapToScene()、view.mapFromScene()这几个方法),屏幕中心的scene位置可以通过编辑窗口长宽的一半并通过view.mapToScene()来转化
来源:https://blog.csdn.net/weixin_40301728/article/details/109654031
猜你喜欢
- 一、首先我们来填个坑支付验签失败这个问题折磨了我两天,官方文档比较含糊不清。各种百度下来的方法试过之后也不尽人意,最后发现问题是没有二次签名
- 本文实例讲述了Python时间的精准正则匹配方法。分享给大家供大家参考,具体如下:要用正则表达式精准匹配时间,其实并不容易方式一:>&
- 遇到的问题当时自己在使用Alexnet训练图像分类问题时,会出现损失在一个epoch中增加,换做下一个epoch时loss会骤然降低,一开始
- 出差做PPT,要放一些图片上去,原图太大必须resize,十几张图片懒得一一处理了,最近正好在学python,最好的学习方式就是使用,于是写
- Readme:blog address:摘要:编写登录接口输入用户名、密码认证成功后显示欢迎信息输错3次后锁定关键词:循环;判断;外部数据读
- 一、location 对象是什么?window 对象给我们提供了一个 location 属性用于获取或设置窗体的 URL,并且可以用于解析
- DROP TABLE 数据表名称 (永久性删除一个数据表) 删除记录:delete from&nbs
- 1、jsp页面,携带值跳转到新页 original.jsp var btnClick = {'click .showne
- 在python3.6版本中去掉了os.path.walk()函数os.walk()函数声明:walk(top,topdown=True,on
- 一、Python 矩阵基本运算引入 numpy 库import numpy as np1. python矩阵操作1)使用
- 背景刚入行的同学,看到在SQL语句中出现where 1 = 1这样的条件可能会有所困惑,而长时间这样使用的朋友可能又习以为常。那么,你是否还
- 注:对多选按钮操作。 1:批量全选添加、批量移除。 2:行单选添加、移除。 3:分页之后(全选或不选)状态标识依然存在 /* *****&g
- 大家可能都不大熟悉关于pdb这个模块,实际上就是python中的内置模块,主要作用于命令行调试代码,下面我们将通过是哪个小结给大家详细介绍下
- 在python中安装了lxml-4.2.1,在使用时发现导入etree时IDE中报错Unresolved reference其实发现,不影响
- 本文实例讲述了Python使用pymysql模块操作mysql增删改查。分享给大家供大家参考,具体如下:# -*- coding:utf-8
- <script type="text/javascript"> // Close HTML Tags ---
- python3 shelve模块的详解一、简介在python3中我们使用json或者pickle持久化数据,能dump多次,但只能load一
- 起步Python 提供的多线程模型中并没有提供读写锁,读写锁相对于单纯的互斥锁,适用性更高,可以多个线程同时占用读模式的读写锁,但是只能一个
- 🚩 前言本次实现了一个在浏览器中运行的简陋的人脸检测功能,由于水平有限,这里使用表单上传图片,只能一次检测一张人脸。实现过程中遇到的主要问题
- 因为工作(懒惰),几年了,断断续续学习又半途而废了一个又一个技能。试着开始用博客记录学习过程中的问题和解决方式,以便激励自己和顺便万一帮助了