python使用tkinter打造三維繪圖系統(tǒng)的示例代碼
Python繪圖系統(tǒng)系列:python將matplotlib嵌入到tkinter中的步驟詳解_python_腳本之家 (jb51.net)
輸入數(shù)據(jù)
三維繪圖需要一個新的坐標變量,設置為z,這個改改UI就可以辦到,并不困難。但是,此前用于設置x和y數(shù)據(jù)的函數(shù)實在是過于雷同,如果再寫一個設置z軸的,那么這個繪圖系統(tǒng)里就相當于是有了3個一毛一樣的函數(shù),十分離譜,所以為了簡化代碼,可以將所有的數(shù)據(jù)輸入框設為一個字典,然后挨個生成xyz的輸入框,其中setFrmCtrl函數(shù)如下
def setFrmCtrl(self, frmCtrl): frm = ttk.Frame(frmCtrl, width=320) frm.pack(side=tk.TOP, fill=tk.X) self.setCtrlButtons(frm) self.entrys = {} for flag in 'xyz': frm = ttk.Frame(frmCtrl) frm.pack(side=tk.TOP, fill=tk.X) self.setFrmAxis(frm, flag)
setFrmAxis
則沒什么好說的,只是新增了一個參數(shù)而已。
def setFrmAxis(self, frm, flag): tk.Label(frm, text=flag).pack(side=tk.LEFT) self.entrys[flag] = tk.Entry(frm) self.entrys[flag].pack(side=tk.LEFT, fill=tk.X)
加載數(shù)據(jù)
此前,分別用 self.xs
和 self.ys
來表示x和y軸數(shù)據(jù),這又是一個雷同。為了簡化代碼,將變量也設做字典,在初始化的init函數(shù)中添加
self.data = {}
然后將加載數(shù)據(jù)的函數(shù)改寫為
def btnLoadData(self): name = askopenfilename() data = np.genfromtxt(name) for flag, i in enumerate()'xyz': if i >= data.shape[1]: return self.data[flag] = data[:,i] setEntry(self.entrys[flag], 'data')
然后新建一個用來讀取Entry的函數(shù),考慮到x和y都有可能用類似 1,1,5
的形式生成,所以先做一個檢測數(shù)組的全局函數(shù)
def detectArray(s): return s.rstrip('0123456789:, ')==''
然后是readEntrys函數(shù),考慮到在函數(shù)表達式中,用x和y指代self.data[‘x’]和selfdata[‘y’],所以需要新建局部變量x和y,以確保eval函數(shù)的正常使用。
def readEntrys(self): for flag in 'xyz': label = self.entrys[flag].get() if label != 'data': if detectArray(label): label = f"np.linspace({label})" self.data[flag] = eval(self.entrys[flag].get()) if flag =='x' : x = self.data['x'] elif flag =='y' : y = self.data['y'] if self.entrys['z'].get()=="": del self.data['z']
繪圖函數(shù)
最后,就是繪圖功能的實現(xiàn),由于有了readEntrys函數(shù),從而btnDrawImg函數(shù)變得更加專注,只需復制調(diào)用專門的繪圖函數(shù)就可以了。三維繪圖函數(shù)和二維繪圖函數(shù)其實沒什么區(qū)別,只要繪制的還是plot圖,區(qū)別只是多加了一個z軸坐標而已。
def btnDrawImg(self): self.readEntrys() self.fig.clf() if 'z' in self.data: self.drawPlot3D() else: self.drawPlot() self.fig.subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.08) self.canvas.draw()
由于把用于設置邊框?qū)挾鹊膕ubplots_adjust以及canvas.draw放在了btnDrawImg這個函數(shù)中,所以drawPlot函數(shù)也需要做適當?shù)木?。而drawPlot3D只是將projection設為‘3d’,同時添加一組z坐標而已。
def drawPlot(self): ax = self.fig.add_subplot() ax.plot(self.data['x'], self.data['y']) def drawPlot3D(self): ax = self.fig.add_subplot(projection='3d') ax.plot(self.data['x'], self.data['y'], self.data['z'])
至此,就可以看一下效果了
源代碼
最后,附上源代碼
import tkinter as tk import tkinter.ttk as ttk from tkinter.filedialog import askopenfilename import matplotlib as mpl mpl.use('TkAgg') import matplotlib.pyplot as plt from matplotlib.backends.backend_tkagg import ( FigureCanvasTkAgg, NavigationToolbar2Tk) from matplotlib.figure import Figure import numpy as np def setEntry(e, text): e.delete(0, "end") e.insert(0, text) def detectArray(s): return s.rstrip('0123456789:, ')=='' class DarwSystem(): def __init__(self): self.root = tk.Tk() self.root.title("數(shù)據(jù)展示工具") self.data = {} frmCtrl = ttk.Frame(self.root,width=320) frmCtrl.pack(side=tk.RIGHT, fill=tk.Y) self.setFrmCtrl(frmCtrl) frmFig = ttk.Frame(self.root) frmFig.pack(side=tk.LEFT,fill=tk.BOTH,expand=tk.YES) self.setFrmFig(frmFig) self.root.mainloop() def setFrmCtrl(self, frmCtrl): frm = ttk.Frame(frmCtrl, width=320) frm.pack(side=tk.TOP, fill=tk.X) self.setCtrlButtons(frm) self.entrys = {} for flag in 'xyz': frm = ttk.Frame(frmCtrl) frm.pack(side=tk.TOP, fill=tk.X) self.setFrmAxis(frm, flag) def setFrmAxis(self, frm, flag): tk.Label(frm, text=flag).pack(side=tk.LEFT) self.entrys[flag] = tk.Entry(frm) self.entrys[flag].pack(side=tk.LEFT, fill=tk.X) def setCtrlButtons(self, frm): ttk.Button(frm, text="繪圖",width=5, command=self.btnDrawImg).pack(side=tk.LEFT) ttk.Button(frm, text="加載",width=5, command=self.btnLoadData).pack(side=tk.LEFT) def btnLoadData(self): name = askopenfilename() data = np.genfromtxt(name) for i, flag in enumerate('xyz'): if i >= data.shape[1]: return self.data[flag] = data[:,i] setEntry(self.entrys[flag], 'data') def readEntrys(self): for flag in 'xyz': label = self.entrys[flag].get() if label=="": continue if label != 'data': if detectArray(label): label = f"np.linspace({label})" self.data[flag] = eval(self.entrys[flag].get()) if flag =='x' : x = self.data['x'] elif flag =='y' : y = self.data['y'] if self.entrys['z'].get()=="": del self.data['z'] def btnDrawImg(self): self.readEntrys() self.fig.clf() if 'z' in self.data: self.drawPlot3D() else: self.drawPlot() self.fig.subplots_adjust(left=0.1, right=0.95, top=0.95, bottom=0.08) self.canvas.draw() def drawPlot3D(self): ax = self.fig.add_subplot(projection='3d') ax.plot(self.data['x'], self.data['y'], self.data['z']) def drawPlot(self): ax = self.fig.add_subplot() ax.plot(self.data['x'], self.data['y']) def setFrmFig(self, frmFig): self.fig = Figure() self.canvas = FigureCanvasTkAgg(self.fig,frmFig) self.canvas.get_tk_widget().pack( side=tk.TOP,fill=tk.BOTH,expand=tk.YES) self.toolbar = NavigationToolbar2Tk(self.canvas,frmFig, pack_toolbar=False) self.toolbar.update() self.toolbar.pack(side=tk.RIGHT) if __name__ == "__main__": test = DarwSystem()
以上就是python使用tkinter打造三維繪圖系統(tǒng)的示例代碼的詳細內(nèi)容,更多關于python tkinter三維繪圖系統(tǒng)的資料請關注腳本之家其它相關文章!
相關文章
python連接mysql數(shù)據(jù)庫并讀取數(shù)據(jù)的實現(xiàn)
這篇文章主要介紹了python連接mysql數(shù)據(jù)庫并讀取數(shù)據(jù)的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-09-09Python 中如何使用 virtualenv 管理虛擬環(huán)境
這篇文章主要介紹了Python 中使用 virtualenv 管理虛擬環(huán)境的方法,幫助大家更好的理解和使用python,感興趣的朋友可以了解下2021-01-01Python開發(fā)虛擬環(huán)境使用virtualenvwrapper的搭建步驟教程圖解
virtualenvwrapper是用來管理virtualenv的擴展包,用著很方便。這篇文章主要介紹了Python開發(fā)虛擬環(huán)境使用virtualenvwrapper的搭建步驟 ,需要的朋友可以參考下2018-09-09一文帶你了解Python中不同數(shù)據(jù)對象的空值校驗方法
空值校驗在數(shù)據(jù)處理和應用程序開發(fā)中是一個非常重要的任務,Python提供了多種方式來檢查不同數(shù)據(jù)對象(如字符串、列表、字典、集合等)是否為空或包含空值,下面就跟隨小編一起來學習一下吧2024-01-01python批量導入數(shù)據(jù)進Elasticsearch的實例
今天小編就為大家分享一篇python批量導入數(shù)據(jù)進Elasticsearch的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05