Python繪圖系統6:自定義坐標列表控件

文章目錄

    • 自定義坐標列表控件
    • 顯示和隱藏
    • 加載按鈕
    • 坐標設置控件的顯示和隱藏
    • 源代碼

Python繪圖系統:

  • 基礎:將matplotlib嵌入到tkinter 📈簡單的繪圖系統 📈數據導入📈三維繪圖系統
  • 自定義控件:坐標設置控件📉坐標列表控件

自定義坐標列表控件

繪制多組數據是很自然的一個需求,但目前來說只有一套坐標軸,除非是疊加繪制,否則是沒法繪制多組數據的。

為了解決這個問題,最簡單的方案當然是瘋狂地添加坐標軸,x,y,z用完之后再來x1,y1,z1,然后x2,y2,z2,子子孫孫無窮匱也。簡單地說,就是設置一個按鈕,點擊按鈕之后,就會出現一組新的xyz輸入框。

為了實現這個功能,最好把多個坐標輸入控件AxisFrame列在一起,封裝成一個新的控件。由于此前已經做了AxisFrame的自定義,所以這一步不存在難度,初步的代碼如下

class AxisList(ttk.Frame):def __init__(self, master, mode, widths, **options):super().__init__(master, **options)self.pack()self.afs = {}self.initWidgets(mode, widths)def initWidgets(self, mode, widths):for flag in 'xyz':self.afs[flag] = AxisFrame(self, flag, mode, widths)self.afs[flag].pack(side=tk.TOP, fill=tk.X)def setData(self, flag, data=None, **options):return self.afs[flag].setData(data, **options)def setOneMode(self, flag, mode):self.afs[flag].setMode(mode)

然后將DrawSystem中需要更改的地方修改一下就可以了,首先是setFrmCtrl中做下修改,把self.AL作為AxisList對象的名字。其余類似self.afs[flag].XXX(YYY)之類的寫法,均換成self.AL.XXX(flag, YYY)就可以了。

# setFrmCtrl函數
self.AL = AxisList(frmCtrl, 1, [5,10,20])
self.AL.pack(side=tk.TOP, fill=tk.X)

這一步在界面上尚看不出任何端倪。

顯示和隱藏

如果想繪制多組數據,那么就需要很多AxisList,但這玩意一多了之后特別占地方,很難看。解決這個問題,一個比較好的方案是設置一個隱藏按鈕,將這個AxisList做成類似Expander的形式。更改initWidgets函數如下

# 這些代碼都在類中,注意縮進
def initWidgets(self, title, mode, 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.collapsed = Trueself.Click()for flag in 'txyz':self.afs[flag] = AxisFrame(self._c, flag, mode, widths)self.afs[flag].pack(side=tk.TOP, fill=tk.X)
```python其中Click函數是控制顯隱的關鍵函數,內容如下。```python
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

效果為

在這里插入圖片描述

加載按鈕

現在這個測試坐標列表上面還有兩個按鍵,分別是繪圖和加載。繪圖倒是沒什么可說的,但加載按鈕卻很可疑。當我們有多套坐標的時候,一個全局的加載按鈕是讓人疑惑的。

為此,可以將加載按鈕挪到AxisList控件中。由于功能的相似性,這里的確相當于是直接挪過去的,代碼如下

def initFeature(self):frm = ttk.Frame(self._c)frm.pack(side=tk.TOP, fill=tk.X)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]:returnself.setOneMode(flag, "外部導入")self.data[flag] = self.setData(flag, data[:,i])

坐標設置控件的顯示和隱藏

最后,考慮到實際繪圖時,有時要用到兩個坐標軸,有時需要三個,所以最好能對單個的坐標軸進行顯示和隱藏,實現方法與Expander的邏輯如出一轍,在initFeature方法中添加如下內容

self.vis = {L : True for L in 'txyz'}
for flag in 'txyz':btn = ttk.Button(frm, text=flag, width=3)btn.pack(side=tk.LEFT)btn.bind("<Button-1>", self.btnAxisCollapse)

其中self.vis是描述某個坐標控件是否顯示的布爾標記,btn就是對應的按鈕,而self.btnAxisCollapse則是具體的顯示隱藏函數,內容如下

def btnAxisCollapse(self, evt):flag = evt.widget['text']self.vis[flag] = not self.vis[flag]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)

這里的實現過程稍顯繁瑣,主要是考慮到要保證txyz的顯示順序,結果如下

在這里插入圖片描述

源代碼

import tkinter as tk
import tkinter.ttk as ttk
from tkinter.filedialog import askopenfilenameimport matplotlib as mpl
mpl.use('TkAgg')
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figureimport numpy as npclass AxisFrame(ttk.Frame):# widths 是每個控件的寬度def __init__(self, master, label, mode, widths, **options):super().__init__(master, **options)self.pack()self.label = labelself.initVar(mode)self.initWidgets(widths)def initVar(self, mode):self.MODES = ("外部導入", "序列化", "源代碼", "無數據")self.mode = tk.StringVar()self.setMode(mode)def initWidgets(self, widths):tk.Label(self, text=self.label, width=widths[0]).pack(side=tk.LEFT)self.slct = ttk.Combobox(self, width=widths[1], textvariable=self.mode)self.slct['value'] = self.MODESself.slct.pack(side=tk.LEFT)self.entry = tk.Entry(self, width=widths[2])self.entry.pack(padx=5, side=tk.LEFT, fill=tk.X)def setText(self, text):self.entry.delete(0, "end")self.entry.insert(0, text)def get(self):return self.entry.get()def setMode(self, mode):if type(mode) != str:mode = self.MODES[mode]self.mode.set(mode)def setData(self, data=None, **txyz):if self.mode.get() == "序列化":return self.getArray()elif self.mode.get() == "外部導入":return self.loadData(data)else:return self.readPython(**txyz)def readPython(self, t=None, x=None, y=None, z=None):self.data = eval(self.get())return self.datadef loadData(self, data):if type(data) != type(None):self.data = datareturn self.datadef getArray(self):val = self.get()self.data = eval(f"np.linspace({val})")return self.dataclass AxisList(ttk.Frame):def __init__(self, master, title, mode, widths, **options):super().__init__(master, **options)self.pack()self.afs = {}self.data = {}self.initWidgets(title, widths)self.initAxis(mode, widths)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.collapsed = Trueself.Click()self.initFeature()def initAxis(self, mode, widths):for flag in 'txyz':self.afs[flag] = AxisFrame(self._c, flag, mode, widths)self.afs[flag].pack(side=tk.TOP, fill=tk.X)def initFeature(self):frm = ttk.Frame(self._c)frm.pack(pady=2, side=tk.TOP, fill=tk.X)ttk.Button(frm, text="加載",width=5,command=self.btnLoadData).pack(side=tk.LEFT)self.vis = {L : True for L in 'txyz'}for flag in 'txyz':btn = ttk.Button(frm, text=flag, width=3)btn.pack(side=tk.LEFT)btn.bind("<Button-1>", self.btnAxisCollapse)def btnAxisCollapse(self, evt):flag = evt.widget['text']self.vis[flag] = not self.vis[flag]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 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 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.collapseddef setData(self, flag, data=None, **options):return self.afs[flag].setData(data, **options)def setOneMode(self, flag, mode):self.afs[flag].setMode(mode)class DarwSystem():def __init__(self):self.root = tk.Tk()self.root.title("數據展示工具")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.AL = AxisList(frmCtrl, "測試坐標列表", 1, [5,10,20])self.AL.pack(side=tk.TOP, 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]:returnself.AL.setOneMode(flag, "外部導入")self.data[flag] = self.AL.setData(flag, data[:,i])def readDatas(self):dct = {}for flag in 'xyz':self.data[flag] = self.AL.setData(flag, **dct)dct[flag] = self.data[flag]def btnDrawImg(self):self.readDatas()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()

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/42850.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/42850.shtml
英文地址,請注明出處:http://en.pswp.cn/news/42850.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Spring Boot】JdbcTemplate數據連接模板 — JdbcTemplate入門

JdbcTemplate入門 本節從基礎的部分開始介紹什么是JDBC、什么是JdbcTemplate&#xff0c;然后介紹Spring Boot項目如何使用JdbcTemplate操作數據庫。 1.JdbcTemplate簡介 1.1 什么是JDBC JDBC&#xff08;Java Data Base Connectivity&#xff0c;Java數據庫連接&#xff0…

【二叉樹】100. 相同的樹

100. 相同的樹 解題思路 深度優先遍歷首先寫的就是遞歸結束條件當兩個節點都是null 直接返回true當只有其中一個節點是null 返回false當兩個節點的值不相等的時候 直接false然后兩棵樹的左節點 兩個樹的右節點 /*** Definition for a binary tree node.* public class TreeN…

android resoure資源圖片顏色值錯亂

最近androidstudio開發&#xff0c;添加一些顏色值或者drawable資源文件時&#xff0c;運行app,顏色值或者圖片對應不上&#xff0c;暫時找不到原因&#xff0c;望告知。 暫時解決方法&#xff1a;

鏈游再進化 Web3版CSGO來襲

過去幾年&#xff0c;游戲開發者們一直希望借Web3這個價值流通網絡&#xff0c;改造傳統游戲的經濟系統&#xff0c;將虛擬資產的掌管權交給用戶&#xff0c;讓資產自由地在市場流通。 Web3游戲發展史上&#xff0c;涌現過CryptoKitties、Axie Infinity兩大爆款&#xff0c;但…

【C++深入淺出】初識C++中篇(引用、內聯函數)

目錄 一. 前言 二. 引用 2.1 引用的概念 2.2 引用的使用 2.3 引用的特性 2.4 常引用 2.5 引用的使用場景 2.6 傳值、傳引用效率比較 2.7 引用和指針的區別 三. 內聯函數 3.1 內聯函數的概念 3.2 內聯函數的特性 一. 前言 上期說道&#xff0c;C是在C的基礎之上&…

onvif中imaging setting圖像畫質總結!

前言&#xff1a; 大家好&#xff0c;今天給大家來分享一篇關于圖像質量的內容&#xff0c;這個內容是我在做onvif中的imaging setting的時候&#xff0c;關注到里面有關于: brightness(亮度)color saturation(色彩飽和度)contrast(對比度)sharpness(銳度)white balance(白平衡…

C語言刷題指南(二)

&#x1f4d9;作者簡介&#xff1a; 清水加冰&#xff0c;目前大二在讀&#xff0c;正在學習C/C、Python、操作系統、數據庫等。 &#x1f4d8;相關專欄&#xff1a;C語言初階、C語言進階、C語言刷題訓練營、數據結構刷題訓練營、有感興趣的可以看一看。 歡迎點贊 &#x1f44d…

TDI(Time Delay Integration)

TDI&#xff08;Time Delay Integration&#xff09;是一種特殊的圖像采集技術&#xff0c;常用于線陣CCD&#xff08;Charge-Coupled Device&#xff09;相機。TDI技術可以在保持高分辨率的同時增強圖像的信噪比&#xff08;Signal-to-Noise Ratio, SNR&#xff09;&#xff0…

kubesphere 集成 sonar

文章目錄 安裝 helm通過 helm 安裝 sonar配置 SonarQube 服務器創建 SonarQube 管理員令牌SonarQube 配置添加到 ks-installer創建 Webhook 服務器將 SonarQube 服務器添加至 Jenkins將 sonarqubeURL 添加到 KubeSphere 控制臺重啟服務 為新項目創建 SonarQube Token 官方文檔&…

Threejs學習04——球緩沖幾何體環境光以及直線光源

實現隨機多個三角形隨機位置隨機顏色展示效果 這是一個非常簡單基礎的threejs的學習應用&#xff01;本節主要學習的是球面緩沖幾何體在環境光合直線光源下的效果&#xff0c;可以學習到環境光和直線光源的生成效果等功能&#xff01;主要使用的是球緩沖幾何體對象SphereGeome…

使用el-tree實現自定義樹結構樣式

實現效果: 直接上代碼: <template><div><div class"tops"><el-tree :default-expanded-keys"[1]" ref"myTree" :data"data" :props"defaultProps" node-click"handleNodeClick" highlight…

【uniapp】picker mode=“region“ 最簡單的省市區 三級聯動

省市區 picker template <picker mode"region" :value"date" class"u-w-440" change"bindTimeChange"><u--inputborder"bottom"class"u-fb u-f-s-28"placeholder"請選擇省市區"type"te…

第8章 對同步的硬件支持 摘錄

為了保證并行程序執行的正確性和高效性&#xff0c;構建一個共享存儲多處理器系統的硬件必須要解決緩存一致性、存儲一致性和同步原語的支持等問題。 被廣泛使用的同步原語包括鎖lock、柵欄barrier和點對點同步(signal和wait信號量)。舉例來說&#xff0c;鎖和柵欄被大量使用在…

ARM 作業1

一、思維導圖 二、 1. 2. .text 文本段 .globl _start 聲明_start:mov r0,#0mov r1,#0fun:cmp r1,#100bhi stopadd r0,r0,r1add r1,r1,#1b fun stop:b stop .end

C++函數模板和類模板

C另一種編程思想稱為泛型編程&#xff0c;主要利用的技術是模板 C提供兩種模板機制&#xff1a;函數模板和類模板 C提供了模板(template)編程的概念。所謂模板&#xff0c;實際上是建立一個通用函數或類&#xff0c; 其類內部的類型和函數的形參類型不具體指定&#xff0c; 用…

Axios使用CancelToken取消重復請求

處理重復請求&#xff1a;沒有響應完成的請求&#xff0c;再去請求一個相同的請求&#xff0c;會把之前的請求取消掉 新增一個cancelRequest.js文件 import axios from "axios" const cancelTokens {}export const addPending (config) > {const requestKey …

如何區分閏年與平年

首先要明白 地球繞太陽運行周期為365天5小時48分46秒&#xff08;合365.24219天&#xff09;&#xff0c;即一回歸年&#xff08;tropical year&#xff09;。公歷的平年只有365日&#xff0c;比回歸年短約0.2422 日&#xff0c;每四年累積約一天&#xff0c;把這一天加于2月末…

Docker安裝基礎使用練習

目錄 1、安裝Docker-CE 1&#xff09;簡單使用yum方式安裝 ! 2&#xff09;配置鏡像加速&#xff1a; 2、下載系統鏡像&#xff08;Ubuntu、 centos&#xff09; 1&#xff09;先查看我們所需的鏡像有哪些版本。使用search命令&#xff01; 2&#xff09;下載鏡像使用的是pul…

【爬蟲】P1 對目標網站的背景調研(robot.txt,advanced_search,builtwith,whois)

對目標網站的背景調研 檢查 robot.txt估算網站大小識別網站所用技術尋找網站的所有者 檢查 robot.txt 目的&#xff1a; 大多數的網站都會包含 robot.txt 文件。該文件用于指出使用爬蟲爬取網站時有哪些限制。而我們通過讀 robot.txt 文件&#xff0c;亦可以最小化爬蟲被封禁的…

vue中實現文字檢索時候將搜索內容標紅

實現結果 html&#xff1a; <div class"searchBox"><span class"bt">標&#8195&#8195題</span><div class"search"><div class"shuru"><!-- <span class"title">生產經營<…