- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用 Tkinter 和 matplotlib 在 Python 中制作了一个图形查看器 GUI 程序,我在两个图形之间切换。
我有三个问题我不知道如何解决:
import matplotlib
import tkinter as Tk
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
import numpy as np
from tkinter import *
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
from matplotlib.widgets import Slider, RadioButtons
# Seperated out config of plot to just do it once
def config_plot():
fig, ax = plt.subplots()
ax.set(xlabel='time (s)', ylabel='voltage (mV)',
title='Graph One')
return (fig, ax)
class matplotlibSwitchGraphs:
def __init__(self, master):
self.master = master
self.frame = Frame(self.master)
self.fig, self.ax = config_plot()
self.graphIndex = 0
self.canvas = FigureCanvasTkAgg(self.fig, self.master)
self.config_window()
self.draw_graph_one()
self.frame.pack(expand=YES, fill=BOTH)
def config_window(self):
self.canvas.mpl_connect("key_press_event", self.on_key_press)
toolbar = NavigationToolbar2Tk(self.canvas, self.master)
toolbar.update()
self.canvas.get_tk_widget().pack(side=TOP, fill=BOTH, expand=1)
self.button = Button(self.master, text="Quit", command=self._quit)
self.button.pack(side=BOTTOM)
self.button_switch = Button(self.master, text="Switch Graphs", command=self.switch_graphs)
self.button_switch.pack(side=BOTTOM)
def plot_data(self):
def func3(x, y):
return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-(x ** 2 + y ** 2))
dx, dy = 0.05, 0.05
x = np.arange(-3.0, 3.0, dx)
y = np.arange(-3.0, 3.0, dy)
X, Y = np.meshgrid(x, y)
self.extent = np.min(x), np.max(x), np.min(y), np.max(y)
self.Z1 = np.add.outer(range(8), range(8)) % 2 # chessboard
self.Z2 = func3(X, Y)
def draw_graph_one(self):
self.plot_data()
self.ax.remove()
self.ax = plt.imshow(self.Z2, cmap=plt.cm.viridis, alpha=.9, interpolation='bilinear',
extent=self.extent)
self.canvas.draw()
def draw_graph_two(self):
self.plot_data()
self.ax.remove()
self.ax = plt.subplot(1, 2, 1)
self.ax = plt.imshow(self.Z1, cmap=plt.cm.gray, interpolation='nearest',
extent=self.extent)
self.ax = plt.subplot(1, 2, 2)
self.a = plt.imshow(self.Z2, cmap=plt.cm.viridis, alpha=.9, interpolation='bilinear',
extent=self.extent)
self.b = plt.imshow(self.Z1, cmap=plt.cm.gray, interpolation='nearest',
extent=self.extent)
self.canvas.draw()
plt.subplots_adjust(left=0.15, bottom=0.15)
slider_ax = plt.axes([0.06, 0.25, 0.0225, 0.5])
alfa_slider = Slider(slider_ax,
label="Transparency",
valmin=0,
valmax=1,
valinit=0,
orientation="vertical"
)
alfa_slider.on_changed(self.update_slider)
rax = plt.axes([0.06, 0.05, 0.15, 0.15])
radio = RadioButtons(rax, ('Reds', 'Greens', 'Blues', 'Oranges', 'Wistia', 'plasma', 'inferno'), active=0)
radio.on_clicked(self.update_radio)
self.canvas.draw()
def update_slider(self,alpha_):
self.b.set_alpha(alpha_)
self.canvas.draw()
def update_radio(self,label_):
self.b.set_cmap(label_)
self.canvas.draw()
def on_key_press(self,event,toolbar):
print("you pressed {}".format(event.key))
key_press_handler(event, self.canvas, toolbar)
def _quit(self):
self.master.quit() # stops mainloop
def switch_graphs(self):
# Need to call the correct draw, whether we're on graph one or two
self.graphIndex = (self.graphIndex + 1) % 2
if self.graphIndex == 0:
self.draw_graph_one()
else:
self.draw_graph_two()
def main():
root = Tk()
matplotlibSwitchGraphs(root)
root.mainloop()
if __name__ == '__main__':
main()
我试图在函数内部输入 update_slider 和 update_radio 函数,但我不能使用 self.canvas.draw()。
最佳答案
首先回答你的最后一个问题,你的大问题是你试图用一个数字来显示两个单独的图形,而不了解 pyplot 的实际工作原理。这样做是可能的,正如我将在下面概述的那样,但是当您在它们之间切换时,您对图表所做的任何修改都会丢失。我建议阅读 working with multiple axes and figures section of the pyplot tutorial .在 MATLAB 和 pyplot 中的关键要点是,所有绘图函数都应用于最后一个图形和轴。
当您拨打 self.draw_graph_two()
,您创建的最后一个轴是 RadioButtons
.因此,pyplot 将这些轴作为当前轴。当您拨打 self.draw_graph_one()
时第二次(第一次是在您初始化时),它在当前图形和当前轴上绘制图,其中 RadioButtons
是。
要解决此问题,请调用 plt.clf()
作为draw_graph_one
的第一行和 draw_graph_two
, 在尝试绘制新图形之前。这会清除图形,允许从头开始绘制新图(这是您的两个绘制函数所做的)。这允许您在两个绘图之间连续切换,尽管每次切换绘图都会被清除并且对绘图的任何修改都会丢失。您也可以删除 self.ax.remove()
行,因为它们会导致错误并且不需要。
对于前两个问题,可以通过阅读 RadioButtons
的文档来回答这些问题。和 Slider
here .您必须保留对小部件的引用,以便它们保持响应。所以修改你的 draw_graph_two
返回 alfa_slider
和 radio
使这些小部件保持响应。或者,将它们声明为实例变量也会保留一个引用( self.alfa_slider
和 self.radio
)。
所以你的工作图表查看器是:
import matplotlib
import tkinter as tk
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_tkagg import (
FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.backend_bases import key_press_handler
from matplotlib.widgets import Slider, RadioButtons
# Seperated out config of plot to just do it once
def config_plot():
fig, ax = plt.subplots()
ax.set(xlabel='time (s)', ylabel='voltage (mV)',
title='Graph One')
return (fig, ax)
class matplotlibSwitchGraphs:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master)
self.fig, self.ax = config_plot()
self.graphIndex = 0
self.canvas = FigureCanvasTkAgg(self.fig, self.master)
self.config_window()
self.plot_data()
self.draw_graph_one()
self.frame.pack(expand=True, fill=tk.BOTH)
def config_window(self):
self.canvas.mpl_connect("key_press_event", self.on_key_press)
toolbar = NavigationToolbar2Tk(self.canvas, self.master)
toolbar.update()
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.button = tk.Button(self.master, text="Quit", command=self._quit)
self.button.pack(side=tk.BOTTOM)
self.button_switch = tk.Button(self.master, text="Switch Graphs", command=self.switch_graphs)
self.button_switch.pack(side=tk.BOTTOM)
def plot_data(self):
def func3(x, y):
return (1 - x / 2 + x ** 5 + y ** 3) * np.exp(-(x ** 2 + y ** 2))
dx, dy = 0.05, 0.05
x = np.arange(-3.0, 3.0, dx)
y = np.arange(-3.0, 3.0, dy)
X, Y = np.meshgrid(x, y)
self.extent = np.min(x), np.max(x), np.min(y), np.max(y)
self.Z1 = np.add.outer(range(8), range(8)) % 2 # chessboard
self.Z2 = func3(X, Y)
def draw_graph_one(self):
plt.clf()
self.ax = plt.imshow(self.Z2, cmap=plt.cm.viridis, alpha=.9, interpolation='bilinear',
extent=self.extent)
self.canvas.draw()
def draw_graph_two(self):
plt.clf()
self.ax = plt.subplot(1, 2, 1)
self.ax = plt.imshow(self.Z1, cmap=plt.cm.gray, interpolation='nearest',
extent=self.extent)
self.ax = plt.subplot(1, 2, 2)
self.a = plt.imshow(self.Z2, cmap=plt.cm.viridis, alpha=.9, interpolation='bilinear',
extent=self.extent)
self.b = plt.imshow(self.Z1, cmap=plt.cm.gray, interpolation='nearest',
extent=self.extent)
self.canvas.draw()
plt.subplots_adjust(left=0.15, bottom=0.15)
slider_ax = plt.axes([0.06, 0.25, 0.0225, 0.5])
self.alfa_slider = Slider(slider_ax,
label="Transparency",
valmin=0,
valmax=1,
valinit=0,
orientation="vertical"
)
self.alfa_slider.on_changed(self.update_slider)
rax = plt.axes([0.06, 0.05, 0.15, 0.15])
self.radio = RadioButtons(rax, ('Reds', 'Greens', 'Blues', 'Oranges', 'Wistia', 'plasma', 'inferno'), active=0)
self.radio.on_clicked(self.update_radio)
self.canvas.draw()
def update_slider(self,alpha_):
self.b.set_alpha(1-alpha_)
self.canvas.draw()
def update_radio(self,label_):
self.b.set_cmap(label_)
self.canvas.draw()
def on_key_press(self,event,toolbar):
print("you pressed {}".format(event.key))
key_press_handler(event, self.canvas, toolbar)
def _quit(self):
self.master.quit() # stops mainloop
def switch_graphs(self):
# Need to call the correct draw, whether we're on graph one or two
self.graphIndex = (self.graphIndex + 1) % 2
if self.graphIndex == 0:
self.draw_graph_one()
else:
self.draw_graph_two()
def main():
root = tk.Tk()
matplotlibSwitchGraphs(root)
root.mainloop()
if __name__ == '__main__':
main()
注意我还做了一些其他的轻微修改。不要使用
from tkinter import *
,您已经在上面导入并使用
import *
是个坏习惯。我反转了滑块以使透明度有意义。
self.plot_data()
仅在
__init__
中调用一次因为它不会改变。
关于python - 如何在两个图形之间切换并保持单选按钮和 slider 更新工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68931326/
我的应用程序包含两部分:网络部分和 GUI。它的工作方式有点像浏览器 - 用户从服务器请求一些信息,服务器发回一些代表某些 View 的数据,然后 GUI 显示它。 现在我已经将网络部分实现为一项服务
给定表达式字符串exp,编写程序检查exp中“{”、“}”、“(”、“)”、“[”、“]的对和顺序是否正确。 package main import ( "fmt" stack "gi
我想要一个简单的脚本在后台保持运行。目前看起来像这样: import keyboard while True: keyboard.wait('q') keyboard.send('ct
我维护着许多 RedHat Enterprise Linux(7 台和 8 台)服务器(>100 台),其中包含不同的应用程序。为了保持理智,我当然会使用 Ansible 等工具,更重要的是,公共(p
我有一个 winforms 应用程序,它在网络服务请求期间被锁定 我已经尝试使用 doEvents 来保持应用程序解锁,但它仍然不够响应, 我怎样才能绕过这个锁定,让应用程序始终响应? 最佳答案 最好
我正在努力在我的项目中获得并保持领先的 0。以下是当前相关的代码: Dim jobNum As String jobNum = Left(r1.Cells(1, 1), 6) r2.Cells(1
我正在尝试在我的 Canvas 中定位元素相对于我的背景。 窗口被重新调整大小,保持纵横比。 背景随着窗口大小而拉伸(stretch)。 问题是一旦重新调整窗口大小,元素位置就会不正确。如果窗口的大小
一直在玩弄 Hibernate 和 PostgreSQL,试图让它按预期工作。 但是由于某种原因,当我尝试将具有@OneToMany 关系的对象与集合中的多个项目保持一致时,除了第一个项目之外,所有项
我想将某些东西提交到 github 存储库,但我(显然)没有任何权利这样做。我对那个 repo 做了一个分支,提交了我的更改并提交了一个 pull-request。 现在,问题是过了一段时间其他人已经
这是一个初学者问题,我仍在考虑“在 OOP 中”,所以如果我错过了手册中的答案或者答案很明显,我深表歉意。 假设我们有一个抽象类型, abstract type My_Abstract_type en
我们正在开展的一些项目在 jQuery 1.4.2 或更早版本中有着深厚的根基,介于缺乏最新版本的性能优势(或语法糖)、使用现已弃用的方法的耻辱以及部署一个积极维护的库的 3 年以上旧版本,升级现在迫
我看到在FMDB 2.0中,作者为线程添加了FMDatabaseQueue。例子是: // First, make your queue. FMDatabaseQueue *queue = [FMDa
我在 NSScrollView 中有一个 NSTableView。 NSTableView 的内容是通过绑定(bind)到 NSArrayController 来提供的,而 NSArrayContro
我在 TreeView 上有一个节点,我手动填充该节点并希望保持排序。通过用户交互,TreeViewItem 上的标题可能会更改,它们应该移动到列表中的适当位置。 我遍历一个 foreach,创建多个
我从主 NSWindow 打开一个 NSWindow。 DropHereWindowController *dropHereWindowController = [[DropHereWindowCon
我需要放置一个 form 3 按钮,当我单击该按钮时,将其显示为按下,其他按钮向上,当我单击另一个按钮时,它应该为“向下”,其他按钮应为“向上” 最佳答案 所有按钮的属性“Groupindex”必须设
我有一个使用 AnyEvent::MQTT 订阅消息队列的 perl 脚本。 目前我想要它做的就是在收到消息时打印出来。我对 perl 完全陌生,所以我正在使用它附带的演示代码,其中包括将 STDIN
如何在 .NET 应用程序中保持 TreeView 控件的滚动位置?例如,我有一个树形 View 控件,并经历了一个向其添加各种节点的过程,并将它们固定在底部。在此过程中,我可以滚动浏览 TreeVi
我维护了大量的 vbscripts,用于在我的网络上执行各种启动脚本,并且有一些我在几乎所有脚本中使用的函数。 除了复制和粘贴之外,有没有人对我如何创建可重用 vbscript 代码库有建议。我并不反
我有一些关于 Azure 自托管的问题。 假设用户 Alex 在物理机 M 上设置了 Windows 自托管代理。当 Alex 注销且计算机进入休眠状态时,代理将脱机。现在,当 Bob 登录同一台计算
我是一名优秀的程序员,十分优秀!