Python绘图系统24:添加辅助坐标轴
文章目录
- 辅助坐标
- 增减坐标轴
- 时间轴**
- 代码优化
- 源代码
Python绘图系统:
- 前置源码: Python打造动态绘图系统
- 📈一 三维绘图系统 📈二 多图绘制系统📈三 坐 标 轴 定 制
- 📈四 定制绘图风格 📈五 数据生成导入📈六 三维动态演示
- 坐标列表进阶:导出数据📌系统菜单📌批量文件导入📌辅助坐标轴
辅助坐标
通过eval实现的源码阅读功能,具有非常强大的定制功能,但落实到具体使用上,坐标输入框中的代码总不能太长。如果想对数据进行复杂的处理,那么就相当于提出了一个新的需求,能否给出一些辅助坐标系用于数据处理。
这个功能并不复杂,而且代码敲到现在,应该可以说是很有经验了,首先在工具栏末尾填上加减号按钮,用于添加删除辅助坐标。
在initFeature结尾加上
btn = ttk.Button(frm, text="+", width=3)
btn.pack(side=tk.LEFT)
btn.bind("<Button-1>", self.addLast)btn = ttk.Button(frm, text="-", width=3)
btn.pack(side=tk.LEFT)
btn.bind("<Button-1>", self.rmLast)
界面变为
增减坐标轴
若想添加辅助坐标轴,那么首先要给坐标轴取一个名字,由于具体计算时都在函数中局部地进行,故而可以用abcdefg这样一直下去,一般不会出太大的问题。另一方面,创建AxisFrame需要空间宽度和控件模式这两个参数,而这个参数是从初始化时由外部传入的,所以在初始化代码中添加两个全局变量
self.afWidth = widths
self.afMode = mode
而addLast
代码如下
def addLast(self, evt):ABC = "abcdefghijklmnopqrs"for a in ABC:if a in self.afs:continueself.afs[a] = AxisFrame(self._a, a, self.afMode, self.afWidth)breakself.updateVisible()
这段代码相当于预设了最多20个辅助坐标,大部分情况下应该是够用了。
减少坐标轴的逻辑和添加坐标轴相反,但在pack_forget之后,不要忘了把这个对象删掉。
def rmLast(self, evt):CBA = "abcdefghijklmnopqrs"[::-1]for a in CBA:if a not in self.afs:continueself.afs[a].pack_forget()del self.afs[a]breakself.updateVisible()
效果如下
时间轴**
在具体绘图时,时间轴和其他坐标轴有着完全不同的操作,这种不同也应该体现在AxisList的布局上。所以下面要为事件轴专门做一个开关,就像最开始的txyz的独立开关按钮一样。
同时,考虑到作图需求,即有些图像不是三个轴能够完全搞定的,比如箭头向量图。所以需要新增几个坐标轴。
self.vis = {L : True for L in 'txyzuvw'}
for u in uvw: self.vis[u] = False
这里需要改动的地方很多很零碎,最重要的地方是dimChanged函数,要把txyz编程’xyzuvw’,
def dimChanged(self, evt):txyz = self.getDim()for flag in 'xyzuvw':self.vis[flag] = flag in txyzself.updateVisible()
代码优化
至此,AxisList就已经有了相对完备的功能,但新增功能之后,还需要做的就是代码的优化,从可读性、复用率的角度对代码进行整理。
首先是文件格式常量,以及字母表,可先将其设为全局变量。
然后,当对话框返回值为空时,需要跳出函数。
另外,控件显示和隐藏功能其实是可以和坐标轴的显隐功能合在一起的,这也可以解决之前一直存在的一个bug。
![]() | ![]() |
源代码
最后,附上源代码。关于AxisList的修改暂时可以告一段落了,接下来将要做的是修改DrawStyle和DrawType这两个class。
import tkinter as tk
import tkinter.ttk as ttk
from tkinter.filedialog import *
from tkinter.simpledialog import *
from tkinter.messagebox import showwarning
import numpy as npfrom aframe import AxisFrame, AskDct
from base import DrawType, DrawStyleclass AxisList(ttk.Frame):def __init__(self, master, title, mode, widths, types, typeDct, # 绘图类型Combobox的参数**options):super().__init__(master, **options)self.pack()self.initConst()self.afs = {}self.data = {}self.afWidth = widthsself.afMode = modeself.initWidgets(title, widths)self.initFeature(types, typeDct)self.initAxis(mode, widths)self.initStyleFrame()def initConst(self):self.ABC = "abcdefghijklmnopqrs"self.FILE_MERGE = [('numpy数组', 'npy'), ('文本文件', 'csv')]self.FILE_ALL = [('文本文件', 'txt'), ('文本文件', 'csv'), ('二进制文件', 'bin')]def initWidgets(self, title, widths):self.btn = ttk.Button(self, text=title, width=sum(widths)+5,command=self.Click)self.btn.pack(side=tk.TOP, fill=tk.X, expand=tk.YES)self._c = ttk.Frame(self) # 此为主控件self._b = ttk.Frame(self._c) # 工具栏控件self._a = ttk.Frame(self._c) # 此为坐标轴self._s = ttk.LabelFrame(self._c, text = "绘图风格")self._b.pack(side=tk.TOP)self._a.pack(side=tk.TOP)self._s.pack(side=tk.TOP)self.collapsed = Trueself.Click()# 初始化工具栏def initFeature(self, types, typeDct):frm = self._bfrm.pack(pady=2, side=tk.TOP, fill=tk.X)btn = ttk.Menubutton(frm, text="功能",width=4)btn.pack(side=tk.LEFT)m = self.initFileMenu(btn)btn.config(menu=m)self.drawType = DrawType(frm, typeDct, func=self.dimChanged)self.drawType.pack(side=tk.LEFT, padx=2)self.vis = {L : True for L in 'txyzuvw'}ttk.Button(frm, text='t', width=3, command=self.showTimeAxis).pack(side=tk.LEFT)btn = ttk.Button(frm, text="+", width=3)btn.pack(side=tk.LEFT)btn.bind("<Button-1>", self.addLast)btn = ttk.Button(frm, text="-", width=3)btn.pack(side=tk.LEFT)btn.bind("<Button-1>", self.rmLast)def addLast(self, evt):for a in self.ABC:if a in self.afs:continueself.afs[a] = AxisFrame(self._a, a, self.afMode, self.afWidth)breakself.updateVisible()def rmLast(self, evt):for a in self.ABC[::-1]:if a not in self.afs:continueself.afs[a].pack_forget()del self.afs[a]breakself.updateVisible()def showTimeAxis(self):self.vis['t'] = not self.vis['t']self.updateVisible()# 设置菜单def initFileMenu(self, btn):top = tk.Menu(btn, tearoff=False)menuDct = {"导入" : {"按坐标轴" : self.mImportOne, "合并导入" : self.mImportMerge, "多文件导入": self.mImportAll},"导出" : {"合并导出" : self.mExportMerge,"全部导出" : self.mExportAll,"单轴导出" : self.mExportOne},"窗口" : { "风格" : self.btnShowStyle}}for key in menuDct:m = tk.Menu(top, tearoff=False)for L,C in menuDct[key].items():m.add_command(label=L, command = C)top.add_cascade(label=key, menu=m)self.showStyle = Falsereturn top# 加载数据def btnLoadData(self):name = askopenfilename()data = np.genfromtxt(name)for i, flag in enumerate('xyzuvw'):if i >= data.shape[1]:returnself.setOneMode(flag, "外部导入")self.data[flag] = self.setData(flag, data[:,i])def mImportOne(self):fs = askstring("设置参数", "坐标轴间按照逗号分开")fs = fs.replace(",", ",").split(',')for f in fs:if f not in self.getDim():showwarning("您输入的坐标轴并不存在")continueself.afs[f].setMode("外部导入")self.afs[f].slctChanged(None)self.afs[f].btnImportComplex(None) def mImportAll(self):fs = askopenfilenames(filetypes=self.FILE_ALL)for i,f in enumerate(self.getDim()):if i == len(fs) : returnself.afs[f].setMode("外部导入")self.afs[f].slctChanged(None)self.afs[f].btnImportSimple(None)def mImportMerge(self):path = askopenfilename(filetypes==self.FILE_MERGE)if path == "" : returnif path.endswith('.npy'):data = np.load(path)else:data = np.loadtxt(path)for i,f in enumerate(self.getDim()):if i == len(data): continueself.afs[f].setMode("外部导入")self.afs[f].slctChanged(None)self.afs[f].data = data[i]def mExportMerge(self):path = asksaveasfilename(filetypes=self.FILE_MERGE, initialfile=True)if path == "" : returnarr = np.array([self.afs[flag].data for flag in self.getDim()])if path.endswith('.npy'):arr.tofile(path)else:np.savetxt(path, arr, delimiter=', ')def mExportAll(self):path = askdirectory()if path == "": returnfor flag in self.getDim():#self.afs[flag].save(path)passdef mExportOne(self):flag = askstring("请选择输出的轴")if flag not in self.getDim():showwarning("您输入的坐标轴并不存在")#self.afs[flag].save()# 初始化坐标轴def initAxis(self, mode, widths):for flag in 'txyzuvw':self.afs[flag] = AxisFrame(self._a, flag, mode, widths)self.afs[flag].pack(side=tk.TOP, fill=tk.X)self.vis = {L : L in self.getDim() for L in 'txyzuvw'}self.updateVisible()# 初始化风格控件def initStyleFrame(self):self.drawStyle = DrawStyle(self._s)self.drawStyle.pack(side=tk.TOP, fill=tk.X)# 维度改变时的回调函数def dimChanged(self, evt):txyz = self.getDim()for flag in 'xyzuvw':self.vis[flag] = flag in txyzself.updateVisible()# 更新隐藏和显示def updateVisible(self):for key in self.afs:self.afs[key].pack_forget()for key in self.ABC:if key in self.afs:self.afs[key].pack(side=tk.TOP, fill=tk.X)for flag in 'txyzuvw':if self.vis[flag]:self.afs[flag].pack(side=tk.TOP, fill=tk.X)if self.showStyle:self._s.pack(side=tk.TOP, fill=tk.X)else:self._s.pack_forget()def btnShowStyle(self):self.showStyle = not self.showStyleself.updateVisible()def getSub(self):return self.drawType.getSub()def getProj(self):return self.drawType.getProj()def getType(self):return self.drawType.getType()def getDim(self):xyz = self.getXYZ()if self.vis['t']:xyz = 't' + xyzreturn xyzdef getXYZ(self):return self.drawType.getDim()def hasTimeAxis(self):return self.vis['t']def getStyle(self):return self.drawStyle.getVarDct()def Click(self):if self.collapsed:self._c.pack(side=tk.TOP, fill=tk.BOTH, expand=tk.YES) else:self._c.pack_forget()self.collapsed = not self.collapsed# 设置数据def setData(self, flag, data=None, **options):return self.afs[flag].setData(data, **options)# 设置模式def setOneMode(self, flag, mode):self.afs[flag].setMode(mode)
相关文章:

Python绘图系统24:添加辅助坐标轴
文章目录 辅助坐标增减坐标轴时间轴**代码优化源代码 Python绘图系统: 前置源码: Python打造动态绘图系统📈一 三维绘图系统 📈二 多图绘制系统📈三 坐 标 轴 定 制📈四 定制绘图风格 📈五 数据…...
Java自学网站--十几个网站的分析与评测
原文网址:Java自学网站--十几个网站的分析与评测_IT利刃出鞘的博客-CSDN博客 简介 很多想学Java的人不知道怎样选教程,本文对Java自学网站进行评测。 本文不带主观倾向,只客观分析各个网站的区别。 第1类:大型培训机构(黑马等…...
java接口怎么写
Java接口是一种定义规范的抽象类型,可以包含常量和方法的声明。接口在Java编程中具有重要的作用,可以实现代码的重用和灵活性。本文将详细介绍Java接口的编写方式和使用方法。 一、什么是Java接口 在Java中,接口(Interface&…...

第8章 Spring(二)
8.11 Spring 中哪些情况下,不能解决循环依赖问题 难度:★★ 重点:★★ 白话解析 有一下几种情况,循环依赖是不能解决的: 1、原型模式下的循环依赖没办法解决; 假设Girl中依赖了Boy,Boy中依赖了Girl;在实例化Girl的时候要注入Boy,此时没有Boy,因为是原型模式,每次都…...
从0开始python学习-24.selenium 浏览器常见的操作
1. 浏览器的最大化/最小化:maximize_window () / minimize_window() 2. 设置浏览器的宽高:set_window_size() 3. 设置浏览器的位置:set_window_position(0,0) —》左上角为原点 4. 刷新:refresh() 5. 前进:forward() 6…...

Canal实现数据同步
1、Canal实现数据同步 canal可以用来监控数据库数据的变化,从而获得新增数据,或者修改的数据。 1.1 Canal工作原理 原理相对比较简单: 1、canal模拟mysql slave的交互协议,伪装自己为mysql slave,向mysql master发送…...
数据库学习笔记——DDL
数据库学习笔记——DDL 建立EMPLOYEE数据库: CREATE TABLE employee(employee_ID int not null,employee_name varchar(20) not null,street varchar(20) not null,city varchar(20) not null,PRIMARY KEY(employee_ID) );CREATE TABLE company(company_name varc…...
MATLAB算法实战应用案例精讲-【人工智能】边缘计算(附python代码实现)
目录 前言 几个高频面试题目 边缘计算和云计算的关系 云计算(cloud computing) 边缘计算...

精彩回顾 | 迪捷软件亮相2023世界智能网联汽车大会
2023年9月24日,2023世界智能网联汽车大会(以下简称大会)在北京市圆满落幕。迪捷软件北京参展之行圆满收官。 本次大会由工业和信息化部、公安部、交通运输部、中国科学技术协会、北京市人民政府联合主办,是我国首个经国务院批准的…...
【ShaderLab PBR 嗜血边缘角色_美式朋克风格_“Niohoggr“_角色渲染(第一篇)】
嗜血边缘角色Cyberpunk style Unity 渲染 《嗜血边缘》截取其中的片段如下:资源分析其中Guitar贴图4张模型:人物细节图:人物模型 Inspector面板这里做一个区域区分:Body贴图1_BC贴图1_BC属性:Body贴图2_NBody贴图3_CMBody贴图4_SRMBody贴图4_RGBReflection Probe第一版Sha…...
python经典百题之围圈报数
题目:有n个人围成一圈,顺序排号。从第一个人开始报数(从1到3报数),凡报到3的人退出圈子,问最后留下的是原来第几号的那位。 程序分析 思路1:模拟游戏过程 使用一个循环队列模拟游戏过程,每次循…...
Google Earth Engine(GEE)案例——如何去除和过滤Landsat和sentinel等系列影像集合中的空影像(三种方法)
简介 本文的主要解决的问题是如何去除和过滤Landsat和sentinel等系列影像集合中的空影像?这个主要源于一下的问题: “从图像集中删除空图像”是什么意思?您的脚本将图像集合过滤到没有图像的日期,这会产生包含 0 个图像的图像集合:https: https://code.earthengine.goog…...

Leetcode 69.x的平方根
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。 示例 1࿱…...

Node18.x基础使用总结(二)
Node18.x基础使用总结 1、Node.js模块化1.1、模块暴露数据1.2、引入模块 2、包管理工具2.1、npm2.2、npm的安装2.3、npm基本使用2.4、搜索包2.5、下载安装包2.6、生产环境与开发环境2.7、生产依赖与开发依赖2.8、全局安装2.9、修改windows执行策略2.10、安装包依赖2.11、安装指…...

LCD 的RGB接口(SYNC Mode/ SYNC-DE Mode/ DE Mode)
1、 SYNC Mode Timing Diagram 2、 SYNC-DE Mode Timing Diagram 3、 DE Mode Timing Diagram RGB接口(SYNC Mode/ SYNC-DE Mode/ DE Mode)-CSDN博客...
flink生成水位线记录方式--周期性水位线生成器
背景 在flink基于事件的时间处理中,水位线记录的生成是一个很重要的环节,本文就来记录下几种水位线记录的生成方式的其中一种:周期性水位线生成器 周期性水位线生成器 1.1 BoundedOutOfOrdernessTimeStampExtractor 他会接收一个表示最大延…...

百度资源搜索平台出现:You do not have the proper credential to access this page.怎么办?
Forbidden site not allowed You do not have the proper credential to access this page. If you think this is a server error, please contact the webmaster. 如果你的百度资源平台,点进去出现这个提示,说明您的网站已经被百度清退了。如果你的网站…...

树莓派CM4开启I2C与UART串口登录同时serial0映射到ttyS0 开启多串口
文章目录 前言1. 树莓派开启I2C与UART串口登录2. 开启多串口总结: 前言 最近用CM4的时候使用到了I2C以及多个UART的情况。 同时配置端口映射也存在部分问题。 这里集中记录一下。 1. 树莓派开启I2C与UART串口登录 输入指令sudo raspi-config 跳转到如下界面&#…...
【租车骑绿道】python实现-附ChatGPT解析
1.题目 租车骑绿道 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 部门组织绿道骑行团建活动。租用公共双人自行车骑行,每辆自行车最多坐两人、做大载重M。 给出部门每个人的体重,请问最多需要租用多少双人自行车 输入描述 第一行两个数字m、n,自行车限重m,代表部门总…...

【ONE·Linux || 多线程(一)】
总言 多线程:进程线程基本概念、线程控制、互斥与同步。 文章目录 总言1、基本概念1.1、补充知识1.1.1、堆区细粒度划分1.1.2、虚拟地址到物理空间的转化 1.2、如何理解线程、进程1.2.1、如何理解线程?1.2.2、如何理解进程? 1.3、实践操作1.…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
代理篇12|深入理解 Vite中的Proxy接口代理配置
在前端开发中,常常会遇到 跨域请求接口 的情况。为了解决这个问题,Vite 和 Webpack 都提供了 proxy 代理功能,用于将本地开发请求转发到后端服务器。 什么是代理(proxy)? 代理是在开发过程中,前端项目通过开发服务器,将指定的请求“转发”到真实的后端服务器,从而绕…...

基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

如何在Windows本机安装Python并确保与Python.NET兼容
✅作者简介:2022年博客新星 第八。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏…...

小智AI+MCP
什么是小智AI和MCP 如果还不清楚的先看往期文章 手搓小智AI聊天机器人 MCP 深度解析:AI 的USB接口 如何使用小智MCP 1.刷支持mcp的小智固件 2.下载官方MCP的示例代码 Github:https://github.com/78/mcp-calculator 安这个步骤执行 其中MCP_ENDPOI…...
LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考
目录 lua脚本 记录流水 记录流水的作用 流水什么时候删除 我们在做库存扣减的时候,显示基于Lua脚本和Redis实现的预扣减 这样可以在秒杀扣减的时候保证操作的原子性和高效性 lua脚本 // ... 已有代码 ...Overridepublic InventoryResponse decrease(Inventor…...
深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀”
深入浅出JavaScript中的ArrayBuffer:二进制数据的“瑞士军刀” 在JavaScript中,我们经常需要处理文本、数组、对象等数据类型。但当我们需要处理文件上传、图像处理、网络通信等场景时,单纯依赖字符串或数组就显得力不从心了。这时ÿ…...