文章目录
- 单轴导入
- 多轴导入
- 多文件导入
- 合并导入
- 源代码
Python绘图系统:
- 前置源码: Python打造动态绘图系统
- 📈一 三维绘图系统 📈二 多图绘制系统📈三 坐 标 轴 定 制
- 📈四 定制绘图风格 📈五 数据生成导入📈六 三维动态演示
- 坐标列表进阶:导出数据📌系统菜单
单轴导入
在功能菜单中,提供了三种文件导入接口,分别是单轴导入、合并导入和多文件导入。其中最简单的是单轴导入,毕竟此前已经在AxisFrame中创建了导入文件的功能。
但AxisFrame设置了两种导入模式,右键为复杂模式,可以设置导入信息;左键为简单模式,只按照上次导入的信息来导入文件。那么AxisList中的单轴导入,设为哪种模式比较好呢?
一般来说,如果坐标轴已经处于文件导入模式,那么显然没有必要在AxisList中导入文件,所以从功能菜单进入并打开单轴文件时,一定是尚未设置坐标轴格式的时候,所以选择复杂模式比较合理。
def mImportOne(self):flag = askstring("设置参数", "请选择输出的轴")if flag not in self.getDim():showwarning("您输入的坐标轴并不存在")returnself.afs[flag].setMode("外部导入")self.afs[flag].slctChanged(None)self.afs[flag].btnImportComplex(None)
效果如下
多轴导入
单轴导入的第一步是输入导入文件所在的坐标轴,但目前来说,我们并没有完全发挥出这个简单的参数对话框的功能。因为这里明明是可以输入多个坐标轴的。
所以,接下来就升级其功能,首先把“单轴导入”的字样编程“按坐标轴”,这样可以更加清晰,然后给上一个提示。
修改后的代码如下,这样就可以同时导入多个坐标轴的数据了。
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)
多文件导入
由于有了多轴导入这个操作,所以多文件操作在调用AxisFrame中的函数的时候,就可以使用更加简单快捷的导入方式。
def mImportAll(self):FILES = [('文本文件', 'txt'), ('文本文件', 'csv'), ('二进制文件', 'bin')]fs = askopenfilenames(filetypes=FILES)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)
这里面FILES作为文件夹筛选列表,显然是个常量,而且会被诸多组件所调用。类似的常量也会越来越多,为了便于管理,提高代码的复用率,其实很有必要做一个文件,专门用于存放常量,这个以后再说。
合并导入
合并导入与合并输出在逻辑上是对偶关系,合并输出是将所有文件合在一起后,输出为二进制或者csv,那么合并导入就应该是这个过程的逆过程。
def mImportMerge(self):FILES = [('numpy数组', 'npy'), ('文本文件', 'csv')]path = askopenfilename(filetypes=FILES)if 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]
源代码
最后,附上修改后的alist.py的源代码
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.afs = {}self.data = {}self.initWidgets(title, widths)self.initFeature(types, typeDct)self.initAxis(mode, widths)self.initStyleFrame()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.Frame(self._c) # 此为绘图风格控件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 'txyz'}# 设置菜单def initFileMenu(self, btn):top = tk.Menu(btn, tearoff=False)m = tk.Menu(top, tearoff=False)m.add_command(label="按坐标轴", command = self.mImportOne)m.add_command(label="合并导入", command = self.mImportMerge)m.add_command(label="多文件导入", command = self.mImportAll)top.add_cascade(label="导入", menu=m)m = tk.Menu(top, tearoff=False)m.add_command(label="合并导出", command = self.mExportMerge)m.add_command(label="全部导出", command = self.mExportAll)m.add_command(label="单轴导出", command = self.mExportOne)top.add_cascade(label="导出", menu=m)m = tk.Menu(top, tearoff=False)m.add_command(label="风格", command = self.btnShowStyle)self.showStyle = Falsetop.add_cascade(label="窗口", menu=m)return top# 加载数据def btnLoadData(self):name = askopenfilename()data = np.genfromtxt(name)for i, flag in enumerate('xyz'):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):FILES = [('文本文件', 'txt'), ('文本文件', 'csv'), ('二进制文件', 'bin')]fs = askopenfilenames(filetypes=FILES)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):FILES = [('numpy数组', 'npy'), ('文本文件', 'csv')]path = askopenfilename(filetypes=FILES)if 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):FILES = [('numpy数组', 'npy'), ('文本文件', 'csv')]path = asksaveasfilename(filetypes=FILES, initialfile=True)arr = 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()for 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 'txyz':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 'txyz'}self.updateVisible()# 初始化风格控件def initStyleFrame(self):self.sf = ttk.LabelFrame(self._s, text="绘图风格")self.drawStyle = DrawStyle(self.sf)self.drawStyle.pack(side=tk.TOP, fill=tk.X)# 维度改变时的回调函数def dimChanged(self, evt):txyz = self.getDim()for flag in 'txyz':self.vis[flag] = flag in txyzself.updateVisible()# 更新隐藏和显示def updateVisible(self):for flag in 'txyz':self.afs[flag].pack_forget()for flag in 'txyz':if self.vis[flag]:self.afs[flag].pack(side=tk.TOP, fill=tk.X)def btnShowStyle(self):self.showStyle = not self.showStyleif self.showStyle:self.sf.pack(side=tk.TOP, fill=tk.X)else:self.sf.pack_forget()self._s.height = 0def getSub(self):return self.drawType.getSub()def getProj(self):return self.drawType.getProj()def getType(self):return self.drawType.getType()def getDim(self):return self.drawType.getDim()def getXYZ(self):return self.getDim().replace("t", "")def hasTimeAxis(self):return "t" in self.getDim()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)