Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 Tkinter & matplotlib
#1
Hey!

I've been trying to solve a problem with matlib and Tkinter where i am unable to assign a number to points in a subplot. I'm trying to make a script for creating Bezier curves for my homework assignment and have been stuck on this.

import tkinter
from tkinter import *

from matplotlib.backends.backend_tkagg import *
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
from matplotlib import animation

import numpy as np
from scipy.special import comb


def inputik():
    global nPoints
    fig.clear("all")
    nPoints = int(pocetbodu_entry.get())
    pocetbodu_entry.delete(0, "end")
    vykresleni()

def bernstein_poly(i, n, t):
    """
     Bernsteinův polynom
     t ... parametr
     n ... počet bodů
     i ... (počet bodů - 1)

    """

    return comb(n, i) * ( t**(n-i) ) * (1 - t)**i


def bezier_curve(points, nTimes=1000):
    """
       Ze zadaných bodů a kroku sestrojí bezierovu křivku
    """

    nPoints = len(points)
    xPoints = np.array([p[0] for p in points])
    yPoints = np.array([p[1] for p in points])

    t = np.linspace(0.0, 1.0, nTimes)

    polynomial_array = np.array([ bernstein_poly(i, nPoints-1, t) for i in range(0, nPoints)   ])

    xvals = np.dot(xPoints, polynomial_array)
    yvals = np.dot(yPoints, polynomial_array)

    return xvals, yvals


def vykresleni():

    if __name__ == "__main__":
        from matplotlib import pyplot as plt
        global ax1

        #nPoints = (pocetbodu_entry.get())
        points = np.random.rand(nPoints, 2) * 200
        xpoints = [p[0] for p in points]
        ypoints = [p[1] for p in points]


        xvals, yvals = bezier_curve(points, nTimes=1000)

        ax1 = fig.add_subplot(111).plot(xvals, yvals)
        ax2 = fig.add_subplot(111).plot(xpoints, ypoints, "ro")
        for nr in range(len(points)):
           ax2.text(points[nr][0], points[nr][0], nr)

        for i in range(nPoints-1):
            pomocna_1x = [xpoints[i], xpoints[i+1]]
            pomocna_1y = [ypoints[i], ypoints[i+1]]
            ax3=fig.add_subplot(111).plot(pomocna_1x, pomocna_1y,'b--', linewidth=2)


        canvas.draw()


# canvas a vykreslovací ploška

root = tkinter.Tk()
root.wm_title("Beziereček")


fig = plt.Figure(figsize=(5, 4), dpi=100, frameon=False)
canvas = FigureCanvasTkAgg(fig, master=root)  # A tk.DrawingArea.
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)

toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)


def on_key_press(event):
    print("you pressed {}".format(event.key))
    key_press_handler(event, canvas, toolbar)


canvas.mpl_connect("key_press_event", on_key_press)


def konec():
    root.quit()
    root.destroy()


#tlačítka a blbítka

pocetbodu = Label(root, text = "Počet řídících bodů: ")
pocetbodu_entry = Entry(root)
buttonQuit = Button(master=root, text="Quit", command=konec)
buttonQuit.pack(side=tkinter.BOTTOM)
buttonSubmit = Button(master=root, text="Submit", command=inputik)
buttonSubmit.pack(side=tkinter.BOTTOM)
pocetbodu_entry.pack(side=tkinter.BOTTOM)
pocetbodu.pack(side=tkinter.BOTTOM)



tkinter.mainloop()
here's the problematic part

        #nPoints = (pocetbodu_entry.get())
        points = np.random.rand(nPoints, 2) * 200
        xpoints = [p[0] for p in points]
        ypoints = [p[1] for p in points]


        xvals, yvals = bezier_curve(points, nTimes=1000)

        ax1 = fig.add_subplot(111).plot(xvals, yvals)
        ax2 = fig.add_subplot(111).plot(xpoints, ypoints, "ro")
        for nr in range(len(points)):
           ax2.text(points[nr][0], points[nr][0], nr)
since matlib is creating a weird list as ax2, I seem to be unable to assign the numbers to the indiviual points.

Thanks in advance! Have a good day
Quote
#2
You are trying to use an undefined object pocetbodu_entry

Error:
Exception in Tkinter callback Traceback (most recent call last): File "/home/captainkirk/.pyenv/versions/3.7.4/lib/python3.7/tkinter/__init__.py", line 1705, in __call__ return self.func(*args) File "/media/captainkirk/Data-3TB/projects/T-Z/T/TryStuff/src/PyMatplotlib.py", line 17, in inputik nPoints = int(pocetbodu_entry.get()) NameError: name 'pocetbodu_entry' is not defined
Quote
#3
(Nov-21-2019, 07:34 PM)Larz60+ Wrote: You are trying to use an undefined object pocetbodu_entry

Error:
Exception in Tkinter callback Traceback (most recent call last): File "/home/captainkirk/.pyenv/versions/3.7.4/lib/python3.7/tkinter/__init__.py", line 1705, in __call__ return self.func(*args) File "/media/captainkirk/Data-3TB/projects/T-Z/T/TryStuff/src/PyMatplotlib.py", line 17, in inputik nPoints = int(pocetbodu_entry.get()) NameError: name 'pocetbodu_entry' is not defined

That is defined at the end
pocetbodu = Label(root, text = "Počet řídících bodů: ")
pocetbodu_entry = Entry(root)
buttonQuit = Button(master=root, text="Quit", command=konec)
buttonQuit.pack(side=tkinter.BOTTOM)
buttonSubmit = Button(master=root, text="Submit", command=inputik)
buttonSubmit.pack(side=tkinter.BOTTOM)
pocetbodu_entry.pack(side=tkinter.BOTTOM)
pocetbodu.pack(side=tkinter.BOTTOM)
That shouldn't be the problem, because without the problematic part with the for cycle that should assign number to each points, the script works just fine, I just really need those points to be labeled
Quote
#4
It needs to defined before you execute line 17
Quote
#5
(Nov-22-2019, 02:37 AM)Larz60+ Wrote: It needs to defined before you execute line 17

Line 17 is part of a function, which gets called after the button is called, this part is working fine. The variable succesfully gets its value from the entry line, problem is after that with the subplot from matlib.
Quote
#6
Again:
The error is:
Error:
Exception in Tkinter callback Traceback (most recent call last): File "/home/captainkirk/.pyenv/versions/3.7.4/lib/python3.7/tkinter/__init__.py", line 1705, in __call__ return self.func(*args) File "/media/captainkirk/Data-3TB/projects/T-Z/T/TryStuff/src/PyMatplotlib.py", line 17, in inputik nPoints = int(pocetbodu_entry.get()) NameError: name 'pocetbodu_entry' is not defined
Which very clearly states that 'pocetbodu_entry' is not defined

I suggest that you run step by step through a debugger and watch the program flow.
Quote
#7
(Nov-22-2019, 04:43 PM)Larz60+ Wrote: Again:
The error is:
Error:
Exception in Tkinter callback Traceback (most recent call last): File "/home/captainkirk/.pyenv/versions/3.7.4/lib/python3.7/tkinter/__init__.py", line 1705, in __call__ return self.func(*args) File "/media/captainkirk/Data-3TB/projects/T-Z/T/TryStuff/src/PyMatplotlib.py", line 17, in inputik nPoints = int(pocetbodu_entry.get()) NameError: name 'pocetbodu_entry' is not defined
Which very clearly states that 'pocetbodu_entry' is not defined

I suggest that you run step by step through a debugger and watch the program flow.

I am getting different error, I'm sorry if I am misunderstanding something, but as far as I can understand it, pocetbodu_entry is defined and works fine, its the line 68 which I can't figure out, without the for cycle on line 67, everything works fine and gets ploted.

Error:
C:/Users/Admin/Downloads/Škola/Python projects/Hangman/testtest.py:66: MatplotlibDeprecationWarning: Adding an axes using the same arguments as a previous axes currently reuses the earlier instance. In a future version, a new instance will always be created and returned. Meanwhile, this warning can be suppressed, and the future behavior ensured, by passing a unique label to each axes instance. ax2 = fig.add_subplot(111).plot(xpoints, ypoints, "ro") Exception in Tkinter callback Traceback (most recent call last): File "C:\Program Files (x86)\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__ return self.func(*args) File "C:/Users/Admin/Downloads/Škola/Python projects/Hangman/testtest.py", line 19, in inputik vykresleni() File "C:/Users/Admin/Downloads/Škola/Python projects/Hangman/testtest.py", line 68, in vykresleni ax2.text(points[nr][0], points[nr][0], nr) AttributeError: 'list' object has no attribute 'text'
Quote
#8
I recopied your script and am getting same error now.
I'll revisit the code after I finish this session.
Quote
#9
OK, now that My code copy is correct, I added some debugging printouts as follows:
import tkinter
from tkinter import *
 
from matplotlib.backends.backend_tkagg import *
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
from matplotlib import animation
 
import numpy as np
from scipy.special import comb
 
 
def inputik():
    global nPoints
    fig.clear("all")
    nPoints = int(pocetbodu_entry.get())
    pocetbodu_entry.delete(0, "end")
    vykresleni()
 
def bernstein_poly(i, n, t):
    """
     Bernsteinův polynom
     t ... parametr
     n ... počet bodů
     i ... (počet bodů - 1)
 
    """
 
    return comb(n, i) * ( t**(n-i) ) * (1 - t)**i
 
 
def bezier_curve(points, nTimes=1000):
    """
       Ze zadaných bodů a kroku sestrojí bezierovu křivku
    """
 
    nPoints = len(points)
    xPoints = np.array([p[0] for p in points])
    yPoints = np.array([p[1] for p in points])
 
    t = np.linspace(0.0, 1.0, nTimes)
 
    polynomial_array = np.array([ bernstein_poly(i, nPoints-1, t) for i in range(0, nPoints)   ])
 
    xvals = np.dot(xPoints, polynomial_array)
    yvals = np.dot(yPoints, polynomial_array)
 
    return xvals, yvals
 
 
def vykresleni():
 
    if __name__ == "__main__":
        from matplotlib import pyplot as plt
        global ax1
 
        #nPoints = (pocetbodu_entry.get())
        points = np.random.rand(nPoints, 2) * 200
        xpoints = [p[0] for p in points]
        ypoints = [p[1] for p in points]
 
 
        xvals, yvals = bezier_curve(points, nTimes=1000)
 
        print(f"\nPoints")
        for x, y in points:
            print(f"x: {x:20}, y: {y:20}")
        print()

        ax1 = fig.add_subplot(111).plot(xvals, yvals)
        ax2 = fig.add_subplot(111).plot(xpoints, ypoints, "ro")
        for nr in range(len(points)):
            print(f"nr: {nr}, points[nr][0]: {points[nr][0]}, points[nr][1]: {points[nr][1]}")
            ax2.text(points[nr][0], points[nr][0], nr)
 
        for i in range(nPoints-1):
            pomocna_1x = [xpoints[i], xpoints[i+1]]
            pomocna_1y = [ypoints[i], ypoints[i+1]]
            ax3=fig.add_subplot(111).plot(pomocna_1x, pomocna_1y,'b--', linewidth=2)
 
 
        canvas.draw()
 
 
# canvas a vykreslovací ploška
 
root = tkinter.Tk()
root.wm_title("Beziereček")
 
 
fig = plt.Figure(figsize=(5, 4), dpi=100, frameon=False)
canvas = FigureCanvasTkAgg(fig, master=root)  # A tk.DrawingArea.
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
 
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
 
 
def on_key_press(event):
    print("you pressed {}".format(event.key))
    key_press_handler(event, canvas, toolbar)
 
 
canvas.mpl_connect("key_press_event", on_key_press)
 
 
def konec():
    root.quit()
    root.destroy()
 
 
#tlačítka a blbítka
 
pocetbodu = Label(root, text = "Počet řídících bodů: ")
pocetbodu_entry = Entry(root)
buttonQuit = Button(master=root, text="Quit", command=konec)
buttonQuit.pack(side=tkinter.BOTTOM)
buttonSubmit = Button(master=root, text="Submit", command=inputik)
buttonSubmit.pack(side=tkinter.BOTTOM)
pocetbodu_entry.pack(side=tkinter.BOTTOM)
pocetbodu.pack(side=tkinter.BOTTOM)
 
 
 
tkinter.mainloop()

which quickly exposed what I think is part the problem.
your line 69 reads ax2.text(points[nr][0], points[nr][0], nr)
and I think it should be: ax2.text(points[nr][0], points[nr][1], nr)

There are still some issues
Is that correct?
Quote
#10
(Nov-22-2019, 05:56 PM)Larz60+ Wrote: OK, now that My code copy is correct, I added some debugging printouts as follows:
import tkinter
from tkinter import *
 
from matplotlib.backends.backend_tkagg import *
from matplotlib.backend_bases import key_press_handler
from matplotlib.figure import Figure
from matplotlib import pyplot as plt
from matplotlib import animation
 
import numpy as np
from scipy.special import comb
 
 
def inputik():
    global nPoints
    fig.clear("all")
    nPoints = int(pocetbodu_entry.get())
    pocetbodu_entry.delete(0, "end")
    vykresleni()
 
def bernstein_poly(i, n, t):
    """
     Bernsteinův polynom
     t ... parametr
     n ... počet bodů
     i ... (počet bodů - 1)
 
    """
 
    return comb(n, i) * ( t**(n-i) ) * (1 - t)**i
 
 
def bezier_curve(points, nTimes=1000):
    """
       Ze zadaných bodů a kroku sestrojí bezierovu křivku
    """
 
    nPoints = len(points)
    xPoints = np.array([p[0] for p in points])
    yPoints = np.array([p[1] for p in points])
 
    t = np.linspace(0.0, 1.0, nTimes)
 
    polynomial_array = np.array([ bernstein_poly(i, nPoints-1, t) for i in range(0, nPoints)   ])
 
    xvals = np.dot(xPoints, polynomial_array)
    yvals = np.dot(yPoints, polynomial_array)
 
    return xvals, yvals
 
 
def vykresleni():
 
    if __name__ == "__main__":
        from matplotlib import pyplot as plt
        global ax1
 
        #nPoints = (pocetbodu_entry.get())
        points = np.random.rand(nPoints, 2) * 200
        xpoints = [p[0] for p in points]
        ypoints = [p[1] for p in points]
 
 
        xvals, yvals = bezier_curve(points, nTimes=1000)
 
        print(f"\nPoints")
        for x, y in points:
            print(f"x: {x:20}, y: {y:20}")
        print()

        ax1 = fig.add_subplot(111).plot(xvals, yvals)
        ax2 = fig.add_subplot(111).plot(xpoints, ypoints, "ro")
        for nr in range(len(points)):
            print(f"nr: {nr}, points[nr][0]: {points[nr][0]}, points[nr][1]: {points[nr][1]}")
            ax2.text(points[nr][0], points[nr][0], nr)
 
        for i in range(nPoints-1):
            pomocna_1x = [xpoints[i], xpoints[i+1]]
            pomocna_1y = [ypoints[i], ypoints[i+1]]
            ax3=fig.add_subplot(111).plot(pomocna_1x, pomocna_1y,'b--', linewidth=2)
 
 
        canvas.draw()
 
 
# canvas a vykreslovací ploška
 
root = tkinter.Tk()
root.wm_title("Beziereček")
 
 
fig = plt.Figure(figsize=(5, 4), dpi=100, frameon=False)
canvas = FigureCanvasTkAgg(fig, master=root)  # A tk.DrawingArea.
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
 
toolbar = NavigationToolbar2Tk(canvas, root)
toolbar.update()
canvas.get_tk_widget().pack(side=tkinter.TOP, fill=tkinter.BOTH, expand=1)
 
 
def on_key_press(event):
    print("you pressed {}".format(event.key))
    key_press_handler(event, canvas, toolbar)
 
 
canvas.mpl_connect("key_press_event", on_key_press)
 
 
def konec():
    root.quit()
    root.destroy()
 
 
#tlačítka a blbítka
 
pocetbodu = Label(root, text = "Počet řídících bodů: ")
pocetbodu_entry = Entry(root)
buttonQuit = Button(master=root, text="Quit", command=konec)
buttonQuit.pack(side=tkinter.BOTTOM)
buttonSubmit = Button(master=root, text="Submit", command=inputik)
buttonSubmit.pack(side=tkinter.BOTTOM)
pocetbodu_entry.pack(side=tkinter.BOTTOM)
pocetbodu.pack(side=tkinter.BOTTOM)
 
 
 
tkinter.mainloop()

which quickly exposed what I think is part the problem.
your line 69 reads ax2.text(points[nr][0], points[nr][0], nr)
and I think it should be: ax2.text(points[nr][0], points[nr][1], nr)

There are still some issues
Is that correct?

Oh yeah, you're right, line 69 should in fact read as you said. Still can't figure out how to get it into the plot
Quote

Top Page

Possibly Related Threads...
Thread Author Replies Views Last Post
  Making a Matplotlib in Tkinter using a slider Jemeronimo 1 1,501 Dec-05-2018, 08:06 AM
Last Post: Gribouillis
  how to install numpy and matplotlib to Tkinter elwolv 4 1,653 Dec-02-2017, 06:17 PM
Last Post: Barrowman

Forum Jump:


Users browsing this thread: 1 Guest(s)