在下面的程序中,我想将 2 个垂直光标放置在 x 轴上的 2 个定义位置处。问题在于,正如您在屏幕截图中看到的那样,光标与“curseur 1”和“curseur 2”字段中选择的值不匹配 此外,当放置光标时,x 轴(比例)的值会消失。当删除光标时,通过取消选择“Curseurs”按钮,光标的值保留在 ax x 上...
from tkinter import *
from tkinter import filedialog,messagebox
from tkinter import ttk
import tkinter as tk
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.patches import Circle
import matplotlib.patches as mpatches
from matplotlib.backend_bases import MouseButton
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,NavigationToolbar2Tk
from matplotlib.widgets import Button,CheckButtons,Slider,Cursor
def gestion_curseurs(event):
global fenetre,fenetre_ouverte,largeur_fenetre,longueur_fenetre,bouton_curseurs,decision_curseurs,label_alerte_curseurs,saisie_curseur_1,variable_curseur_1,saisie_curseur_2,variable_curseur_2,bouton_valider_curseurs
if fenetre_ouverte=="non":
fenetre=tk.Tk()
fenetre.protocol("WM_DELETE_WINDOW",valider_curseurs)
fenetre.title("Gestion des curseurs")
fenetre.resizable(width=False,height=False)
fenetre["bg"]="black"
fenetre_ouverte="oui"
label_curseurs=Label(fenetre,text="GESTION DES CURSEURS",bg="black",fg="white",font=25)
label_curseurs.place(x=0,y=0)
decision_curseurs=tk.BooleanVar(master=fenetre)
bouton_curseurs=tk.Checkbutton(fenetre,text="Curseurs",bg="white",fg="black",font=25,variable=decision_curseurs,onvalue=True,offvalue=False)
bouton_curseurs.place(x=0,y=label_curseurs.winfo_reqheight()+25)
if valeur_curseur_1!="":bouton_curseurs.select()
label_alerte_curseurs=Label(fenetre,text="",bg="black",fg="red",font=25)
label_curseur_1=Label(fenetre,text="Curseur 1 : ",bg="black",fg="blue",font=25)
label_curseur_1.place(x=0,y=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10)
variable_curseur_1=tk.StringVar(master=fenetre)
saisie_curseur_1=tk.Entry(fenetre,textvariable=variable_curseur_1,bg="white",fg="black",insertbackground="black",font=25,width=10)
saisie_curseur_1.place(x=label_curseur_1.winfo_reqwidth(),y=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10)
variable_curseur_1.trace("w",lambda name,index,mode,variable_curseur_1=variable_curseur_1:entree_saisie_curseurs(variable_curseur_1))
label_curseur_2=Label(fenetre,text="Curseur 2 : ",bg="black",fg="red",font=25)
label_curseur_2.place(x=0,y=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10+label_curseur_1.winfo_reqheight()+5)
variable_curseur_2=tk.StringVar(master=fenetre)
saisie_curseur_2=tk.Entry(fenetre,textvariable=variable_curseur_2,bg="white",fg="black",insertbackground="black",font=25,width=10)
saisie_curseur_2.place(x=label_curseur_2.winfo_reqwidth(),y=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10+label_curseur_1.winfo_reqheight()+5)
variable_curseur_2.trace("w",lambda name,index,mode,variable_curseur_2=variable_curseur_2:entree_saisie_curseurs(variable_curseur_2))
bouton_valider_curseurs=tk.Button(fenetre,text="\u2716 Terminer",bg="orange",fg="white",font=25,width=10,command=valider_curseurs)
bouton_valider_curseurs.place(x=0,y=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10+label_curseur_1.winfo_reqheight()+5+label_curseur_2.winfo_reqheight()+25)
largeur_fenetre,longueur_fenetre=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10+label_curseur_1.winfo_reqheight()+5+label_curseur_2.winfo_reqheight()+25+bouton_valider_curseurs.winfo_reqheight(),int(fenetre.winfo_screenheight()/720*500*1.2*1.5)
fenetre.geometry("{}x{}+{}+{}".format(longueur_fenetre,largeur_fenetre,fenetre.winfo_screenwidth()//2-(longueur_fenetre+2*(fenetre.winfo_rootx()-fenetre.winfo_x()))//2,fenetre.winfo_screenheight()//2-(largeur_fenetre+fenetre.winfo_rooty()-fenetre.winfo_y()+fenetre.winfo_rootx()-fenetre.winfo_x())//2))
variable_curseur_1.set(valeur_curseur_1),variable_curseur_2.set(valeur_curseur_2)
def entree_saisie_curseurs(variable_curseurs):
if variable_curseur_1.get()!="":
try:
float(variable_curseur_1.get())
erreur_curseur_1="non"
saisie_curseur_1.configure(fg="black")
except:
erreur_curseur_1="oui"
saisie_curseur_1.configure(fg="red")
else:erreur_curseur_1="vide"
if variable_curseur_2.get()!="":
try:
float(variable_curseur_2.get())
erreur_curseur_2="non"
saisie_curseur_2.configure(fg="black")
except:
erreur_curseur_2="oui"
saisie_curseur_2.configure(fg="red")
else:erreur_curseur_2="vide"
if erreur_curseur_1=="oui" or erreur_curseur_2=="oui":label_alerte_curseurs.configure(text="\u26A0 Saisissez un nombre dans les champs en rouge.",fg="red")
elif erreur_curseur_1!="oui" and erreur_curseur_2=="vide" or erreur_curseur_1=="vide" and erreur_curseur_2!="oui":label_alerte_curseurs.configure(text="\u26A0 Veuillez remplir les champs relatifs aux curseurs.",fg="red")
else:label_alerte_curseurs.configure(text="\u2714",fg="green")
label_alerte_curseurs.place(x=bouton_valider_curseurs.winfo_reqwidth()+10,y=largeur_fenetre-bouton_valider_curseurs.winfo_reqheight()/2-label_alerte_curseurs.winfo_reqheight()/2)
def valider_curseurs():
global fenetre_ouverte,curseur_1,valeur_curseur_1,curseur_2,valeur_curseur_2
try:curseur_1.remove(),curseur_2.remove()
except:pass
if decision_curseurs.get()==False or label_alerte_curseurs["text"]!="\u2714":valeur_curseur_1,valeur_curseur_2="",""
if decision_curseurs.get()==True and label_alerte_curseurs["text"]=="\u2714":
valeur_curseur_1,valeur_curseur_2=variable_curseur_1.get(),variable_curseur_2.get()
curseur_1=ax.axvline(x=variable_curseur_1.get(),color="blue",linestyle="-")
curseur_2=ax.axvline(x=variable_curseur_2.get(),color="red",linestyle="-")
ax.figure.canvas.draw()
try:fenetre.destroy()
except:pass
fenetre_ouverte="non"
def REPRESENTATION_graphe():
global fenetre_ouverte,fig,ax,valeur_curseur_1,valeur_curseur_2
fenetre_ouverte,valeur_curseur_1,valeur_curseur_2="non","",""
x=[1,300,900,1200,1800]
y=[1,2,3,4,5]
# Construction fenêtres Matplotlib
fig,ax=plt.subplots()
axBtn=plt.axes([0.0,0.0,0.1,0.05])
Btn=Button(axBtn,label="Curseurs",color="orange",hovercolor="yellow")
Btn.on_clicked(gestion_curseurs)
# Représentation spectrale
ax.scatter(x,y,s=5,c="red")
plt.show(block=True)
REPRESENTATION_graphe()
如何解决这些问题?
问题出在 Matplotlib 如何处理坐标轴限制和光标交互上。当添加或移除光标时,坐标轴限制会发生变化,从而导致光标位置出现偏移。以下是如何解决这些问题的修改后代码:
from tkinter import *
from tkinter import filedialog,messagebox
from tkinter import ttk
import tkinter as tk
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.patches import Circle
import matplotlib.patches as mpatches
from matplotlib.backend_bases import MouseButton
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,NavigationToolbar2Tk
from matplotlib.widgets import Button,CheckButtons,Slider,Cursor
def gestion_curseurs(event):
global fenetre,fenetre_ouverte,largeur_fenetre,longueur_fenetre,bouton_curseurs,decision_curseurs,label_alerte_curseurs,saisie_curseur_1,variable_curseur_1,saisie_curseur_2,variable_curseur_2,bouton_valider_curseurs
if fenetre_ouverte=="non":
fenetre=tk.Tk()
fenetre.protocol("WM_DELETE_WINDOW",valider_curseurs)
fenetre.title("Gestion des curseurs")
fenetre.resizable(width=False,height=False)
fenetre["bg"]="black"
fenetre_ouverte="oui"
label_curseurs=Label(fenetre,text="GESTION DES CURSEURS",bg="black",fg="white",font=25)
label_curseurs.place(x=0,y=0)
decision_curseurs=tk.BooleanVar(master=fenetre)
bouton_curseurs=tk.Checkbutton(fenetre,text="Curseurs",bg="white",fg="black",font=25,variable=decision_curseurs,onvalue=True,offvalue=False)
bouton_curseurs.place(x=0,y=label_curseurs.winfo_reqheight()+25)
if valeur_curseur_1!="":bouton_curseurs.select()
label_alerte_curseurs=Label(fenetre,text="",bg="black",fg="red",font=25)
label_curseur_1=Label(fenetre,text="Curseur 1 : ",bg="black",fg="blue",font=25)
label_curseur_1.place(x=0,y=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10)
variable_curseur_1=tk.StringVar(master=fenetre)
saisie_curseur_1=tk.Entry(fenetre,textvariable=variable_curseur_1,bg="white",fg="black",insertbackground="black",font=25,width=10)
saisie_curseur_1.place(x=label_curseur_1.winfo_reqwidth(),y=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10)
variable_curseur_1.trace("w",lambda name,index,mode,variable_curseur_1=variable_curseur_1:entree_saisie_curseurs(variable_curseur_1))
label_curseur_2=Label(fenetre,text="Curseur 2 : ",bg="black",fg="red",font=25)
label_curseur_2.place(x=0,y=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10+label_curseur_1.winfo_reqheight()+5)
variable_curseur_2=tk.StringVar(master=fenetre)
saisie_curseur_2=tk.Entry(fenetre,textvariable=variable_curseur_2,bg="white",fg="black",insertbackground="black",font=25,width=10)
saisie_curseur_2.place(x=label_curseur_2.winfo_reqwidth(),y=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10+label_curseur_1.winfo_reqheight()+5)
variable_curseur_2.trace("w",lambda name,index,mode,variable_curseur_2=variable_curseur_2:entree_saisie_curseurs(variable_curseur_2))
bouton_valider_curseurs=tk.Button(fenetre,text="\u2716 Terminer",bg="orange",fg="white",font=25,width=10,command=valider_curseurs)
bouton_valider_curseurs.place(x=0,y=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10+label_curseur_1.winfo_reqheight()+5+label_curseur_2.winfo_reqheight()+25)
largeur_fenetre,longueur_fenetre=label_curseurs.winfo_reqheight()+25+bouton_curseurs.winfo_reqheight()+10+label_curseur_1.winfo_reqheight()+5+label_curseur_2.winfo_reqheight()+25+bouton_valider_curseurs.winfo_reqheight(),int(fenetre.winfo_screenheight()/720*500*1.2*1.5)
fenetre.geometry("{}x{}+{}+{}".format(longueur_fenetre,largeur_fenetre,fenetre.winfo_screenwidth()//2-(longueur_fenetre+2*(fenetre.winfo_rootx()-fenetre.winfo_x()))//2,fenetre.winfo_screenheight()//2-(largeur_fenetre+fenetre.winfo_rooty()-fenetre.winfo_y()+fenetre.winfo_rootx()-fenetre.winfo_x())//2))
variable_curseur_1.set(valeur_curseur_1),variable_curseur_2.set(valeur_curseur_2)
def entree_saisie_curseurs(variable_curseurs):
if variable_curseur_1.get()!="":
try:
float(variable_curseur_1.get())
erreur_curseur_1="non"
saisie_curseur_1.configure(fg="black")
except:
erreur_curseur_1="oui"
saisie_curseur_1.configure(fg="red")
else:erreur_curseur_1="vide"
if variable_curseur_2.get()!="":
try:
float(variable_curseur_2.get())
erreur_curseur_2="non"
saisie_curseur_2.configure(fg="black")
except:
erreur_curseur_2="oui"
saisie_curseur_2.configure(fg="red")
else:erreur_curseur_2="vide"
if erreur_curseur_1=="oui" or erreur_curseur_2=="oui":label_alerte_curseurs.configure(text="\u26A0 Saisissez un nombre dans les champs en rouge.",fg="red")
elif erreur_curseur_1!="oui" and erreur_curseur_2=="vide" or erreur_curseur_1=="vide" and erreur_curseur_2!="oui":label_alerte_curseurs.configure(text="\u26A0 Veuillez remplir les champs relatifs aux curseurs.",fg="red")
else:label_alerte_curseurs.configure(text="\u2714",fg="green")
label_alerte_curseurs.place(x=bouton_valider_curseurs.winfo_reqwidth()+10,y=largeur_fenetre-bouton_valider_curseurs.winfo_reqheight()/2-label_alerte_curseurs.winfo_reqheight()/2)
def valider_curseurs():
global fenetre_ouverte,curseur_1,valeur_curseur_1,curseur_2,valeur_curseur_2, xlim, ylim
try:
curseur_1.remove()
curseur_2.remove()
except:
pass
if decision_curseurs.get()==False or label_alerte_curseurs["text"]!="\u2714":
valeur_curseur_1,valeur_curseur_2="",""
if decision_curseurs.get()==True and label_alerte_curseurs["text"]=="\u2714":
valeur_curseur_1,valeur_curseur_2=float(variable_curseur_1.get()),float(variable_curseur_2.get())
curseur_1=ax.axvline(x=valeur_curseur_1,color="blue",linestyle="-")
curseur_2=ax.axvline(x=valeur_curseur_2,color="red",linestyle="-")
# 保存当前坐标轴限制
xlim = ax.get_xlim()
ylim = ax.get_ylim()
ax.figure.canvas.draw()
# 恢复坐标轴限制
ax.set_xlim(xlim)
ax.set_ylim(ylim)
try:fenetre.destroy()
except:pass
fenetre_ouverte="non"
def REPRESENTATION_graphe():
global fenetre_ouverte,fig,ax,valeur_curseur_1,valeur_curseur_2, xlim, ylim
fenetre_ouverte,valeur_curseur_1,valeur_curseur_2="non","",""
xlim, ylim = None, None
x=[1,300,900,1200,1800]
y=[1,2,3,4,5]
# Construction fenêtres Matplotlib
fig,ax=plt.subplots()
axBtn=plt.axes([0.0,0.0,0.1,0.05])
Btn=Button(axBtn,label="Curseurs",color="orange",hovercolor="yellow")
Btn.on_clicked(gestion_curseurs)
# Représentation spectrale
ax.scatter(x,y,s=5,c="red")
plt.show(block=True)
REPRESENTATION_graphe()
解释:
- 保存和恢复坐标轴限制:
-
在
valider_curseurs
函数中,我们现在在添加或移除光标之前使用ax.get_xlim()
和ax.get_ylim()
保存当前的 x 轴和 y 轴限制。 -
然后,在绘制光标并更新画布之后,我们使用
ax.set_xlim(xlim)
和ax.set_ylim(ylim)
恢复保存的限制。这可以防止坐标轴限制因添加或移除光标而发生变化。 -
将字符串转换为浮点数:
-
在
valider_curseurs
函数中,我们将variable_curseur_1.get()
和variable_curseur_2.get()
的值转换为浮点数,然后再将其用作光标的位置。这可以确保光标放置在正确的位置,即使输入是字符串格式。
通过进行这些更改,光标现在应该始终放置在正确的位置,并且 x 轴比例应该在添加或移除光标后保持稳定。
标签:python,matplotlib,draw,figure,cursors From: 78815244