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】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

从WWDC看苹果产品发展的规律
WWDC 是苹果公司一年一度面向全球开发者的盛会,其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具,对过去十年 WWDC 主题演讲内容进行了系统化分析,形成了这份…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
css3笔记 (1) 自用
outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size:0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格ÿ…...
Mobile ALOHA全身模仿学习
一、题目 Mobile ALOHA:通过低成本全身远程操作学习双手移动操作 传统模仿学习(Imitation Learning)缺点:聚焦与桌面操作,缺乏通用任务所需的移动性和灵活性 本论文优点:(1)在ALOHA…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...