首页 > 编程问答 >matplotlib 光标在图表上的错误位置

matplotlib 光标在图表上的错误位置

时间:2024-07-31 16:37:58浏览次数:13  
标签:python matplotlib draw figure cursors

在下面的程序中,我想将 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()

enter image description here

如何解决这些问题?


问题出在 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()

解释:

  1. 保存和恢复坐标轴限制:
  2. valider_curseurs 函数中,我们现在在添加或移除光标之前使用 ax.get_xlim() ax.get_ylim() 保存当前的 x 轴和 y 轴限制。
  3. 然后,在绘制光标并更新画布之后,我们使用 ax.set_xlim(xlim) ax.set_ylim(ylim) 恢复保存的限制。这可以防止坐标轴限制因添加或移除光标而发生变化。

  4. 将字符串转换为浮点数:

  5. valider_curseurs 函数中,我们将 variable_curseur_1.get() variable_curseur_2.get() 的值转换为浮点数,然后再将其用作光标的位置。这可以确保光标放置在正确的位置,即使输入是字符串格式。

通过进行这些更改,光标现在应该始终放置在正确的位置,并且 x 轴比例应该在添加或移除光标后保持稳定。

标签:python,matplotlib,draw,figure,cursors
From: 78815244

相关文章

  • Python - Class Decorators
    Wehaveusedfunctionstodecoratefunctionsandtodecorateclasses.Now,wewillseehowtodefineaclassasadecorator.Atthestartofthischapter,inthedefinitionofdecorator,wehadseenthatadecoratorisacallable;acallableisanyobject......
  • 基于Python的高校成绩分析【源码+LW+PPT+部署讲解】
    作者主页:编程千纸鹤作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待......
  • 基于Python网络爬虫的电子产品信息查询可视化系统
    作者主页:编程千纸鹤作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待......
  • [SUCTF 2019]Pythonginx (unicode转IDNA域名分割漏洞)
    代码我看到这两个就感觉有问题了,第一个转编码这个搜了一下是unicode转idna的问题,第二个urlopen是Python标准库中urllib.request模块中的一个函数,用于向指定的URL发送HTTP请求并获取响应参考文章:https://xz.aliyun.com/t/6070?time__1311=n4%2BxnD0DgDcmG%3DrDsYoxCqiIQ7KDtH......
  • 基于Python的高校成绩分析【源码+LW+PPT+部署讲解】
    作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与各位高校教师、企......
  • 基于Python网络爬虫的电子产品信息查询可视化系统
    作者简介:Java领域优质创作者、CSDN博客专家、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与各位高校教师、企业......
  • 使用 Python 读取 .xlsx 文件的最快方法
    我正在尝试使用Python将.xlsx文件中的数据读入MySQL数据库。这是我的代码:wb=openpyxl.load_workbook(filename="file",read_only=True)ws=wb['MyWorksheet']conn=MySQLdb.connect()cursor=conn.cursor()cursor.execute("SETautocommit=0"......
  • 《最新出炉》系列初窥篇-Python+Playwright自动化测试-60 - 判断元素是否显示 - 下篇
    1.简介有些页面元素的生命周期如同流星一闪,昙花一现。我们也不知道这个元素在没在页面中出现过,为了捕获这一美好瞬间,让其成为永恒。我们就来判断元素是否显示出现过。在操作元素之前,可以先判断元素的状态。判断元素操作状态也可以用于断言。2.常用的元素判断方法2.1page对象调......
  • 是否有可能在Python中获取客户端计算机的位置
    我想编写一个程序,用python查找客户端计算机的位置。不过,我不介意它的格式如何。我到处尝试过一些东西,但老实说,我对这类事情了解不多,所以我真的不知道从哪里开始。|||我想简单地运行该程序,并将运行该程序的客户端计算机的位置写入控制台。Iwouldliketosimplyrunt......
  • Python:使用 Selenium WebDriver 无法在客户端打开浏览器
    我使用SeleniumWebDriver开发了一个应用程序来打开一些页面。它在本地工作得很好,但我还需要在客户端启动浏览器。我使用Apache2underUbuntu18部署了应用程序。driver=webdriver.Chrome(executable_path="chromedriver",chrome_options=ch......