denis
denis

Reputation: 740

How to hide or show a canvas line controlled by sliders using Checkbuttom from Tkinter?

With the code below it is possible to control the amplitude and frequency of a triangular signal.
Just starting out with Python, I fail to hide or show a given signal using a Checkbutton from tkinter. The few examples found on Internet apply to label texts or images, but none to canvas objects controlled via functions...
Thanks for help

import tkinter as tk
from tkinter import ttk
import numpy as np
from scipy import signal as sg

root = tk.Tk()
root.title('Oscilloscope')
root.geometry("1000x600+0+0")

N1 = 2000
X1 = 1000
O1 = 200

# canva
cnv = tk.Canvas(root, width = 800, height = 400, bg = 'white')
cnv.place(relx=0.5, rely=0.3, anchor=tk.CENTER)
cnv.create_line(400, 0, 400, 400, fill='black', width=1)
cnv.create_line(0, 200, 1000, 200, fill='black', width=1)

# sliders labels
amplitude = ttk.Label(root, text="Amplitude", font=("Arial", 12, "bold"), foreground="black")
amplitude.place(relx=0.3, rely=0.7, anchor=tk.CENTER)
frequence = ttk.Label(root, text="Frequency", font=("Arial", 12, "bold"), foreground="black")
frequence.place(relx=0.7, rely=0.7, anchor=tk.CENTER)

# signal
def draw1(cnv, A1, F1, O1, N1):
    cnv.delete("line1")
    xpts1 = X1 / (N1-1)
    line1 = []
    for i in range(N1):
        x = (i * xpts1)
        y = A1*sg.sawtooth(2*np.pi*F1*i/N1, width=0.5) + O1
        line1.extend((x, y))
    cnv.create_line(line1, fill="red2", width=3, tag="line1")

# control sliders
def ctrl_curseurs_1(*args):
    A1 = A1_valeur.get()
    F1 = F1_valeur.get()
    draw1(cnv, A1, F1, O1, N1)

# horizontal slider for amplitude A1 ############################
def curseur_A1():
    sel = "Value = " + str(value.get(A1))
A1_valeur = tk.IntVar()
A1_frm = ttk.Frame(root)
A1_frm.place(relx=0.3, rely=0.8, anchor=tk.CENTER)
A1_scale = tk.Scale(A1_frm, variable=A1_valeur, command=ctrl_curseurs_1,
                           from_ = -200, to = 200, length=200, showvalue=1, tickinterval=100, orient = tk.HORIZONTAL, resolution=1)
A1_scale.pack(anchor=tk.CENTER)

# horizontal slider for frequency F1 ############################
def curseur_F1():
    sel = "Value = " + str(value.get(F1))
F1_valeur = tk.IntVar()
F1_frm = ttk.Frame(root)
F1_frm.place(relx=0.7, rely=0.8, anchor=tk.CENTER)
F1_scale = tk.Scale(F1_frm, variable=F1_valeur, command=ctrl_curseurs_1,
                           from_ = 0, to = 50, length=200, showvalue=1, tickinterval=10, orient = tk.HORIZONTAL, resolution=1)
F1_scale.pack(anchor=tk.CENTER)

root.mainloop()

Upvotes: 1

Views: 74

Answers (1)

FJSevilla
FJSevilla

Reputation: 4513

Taking into account two things:

  • You can set whether or not a canvas item should be shown using the state attribute, which accepts "hidden" and "normal" as values.

  • You can modify that state once the item is created using canvas.itemconfigure.

With it, you can do something like:

import tkinter as tk
from tkinter import ttk
import numpy as np
from scipy import signal as sg

root = tk.Tk()
root.title('Oscilloscope')
root.geometry("1000x600+0+0")

N1 = 2000
X1 = 1000
O1 = 200

# canvas
cnv = tk.Canvas(root, width = 800, height = 400, bg = 'white')
cnv.place(relx=0.5, rely=0.3, anchor=tk.CENTER)
cnv.create_line(400, 0, 400, 400, fill='black', width=1)
cnv.create_line(0, 200, 1000, 200, fill='black', width=1)

# sliders labels
amplitude = ttk.Label(root, text="Amplitude", font=("Arial", 12, "bold"), foreground="black")
amplitude.place(relx=0.3, rely=0.7, anchor=tk.CENTER)
frequence = ttk.Label(root, text="Frequency", font=("Arial", 12, "bold"), foreground="black")
frequence.place(relx=0.7, rely=0.7, anchor=tk.CENTER)

# signal
def draw1(cnv, A1, F1, O1, N1):
    cnv.delete("line1")
    xpts1 = X1 / (N1-1)
    line1 = []
    for i in range(N1):
        x = (i * xpts1)
        y = A1*sg.sawtooth(2*np.pi*F1*i/N1, width=0.5) + O1
        line1.extend((x, y))
    cnv.create_line(
        line1, fill="red2", width=3, tag="line1",
        state='normal' if check_control_1.get() else 'hidden'
        )

# control sliders
def ctrl_curseurs_1(*args):
    A1 = A1_valeur.get()
    F1 = F1_valeur.get()
    draw1(cnv, A1, F1, O1, N1)

# horizontal slider for amplitude A1 ############################
def curseur_A1():
    sel = "Value = " + str(value.get(A1))

A1_valeur = tk.IntVar()
A1_frm = ttk.Frame(root)
A1_frm.place(relx=0.3, rely=0.8, anchor=tk.CENTER)
A1_scale = tk.Scale(A1_frm, variable=A1_valeur, command=ctrl_curseurs_1,
                           from_ = -200, to = 200, length=200, showvalue=1, tickinterval=100, orient = tk.HORIZONTAL, resolution=1)
A1_scale.pack(anchor=tk.CENTER)

# horizontal slider for frequency F1 ############################
def curseur_F1():
    sel = "Value = " + str(value.get(F1))

F1_valeur = tk.IntVar()
F1_frm = ttk.Frame(root)
F1_frm.place(relx=0.7, rely=0.8, anchor=tk.CENTER)
F1_scale = tk.Scale(F1_frm, variable=F1_valeur, command=ctrl_curseurs_1,
                           from_ = 0, to = 50, length=200, showvalue=1, tickinterval=10, orient = tk.HORIZONTAL, resolution=1)
F1_scale.pack(anchor=tk.CENTER)

check_control_1 = tk.BooleanVar(root, value=False)
ttk.Checkbutton(
    root,
    text="Signal 1",
    variable=check_control_1,
    command=lambda: cnv.itemconfigure(
        "line1", state='normal' if check_control_1.get() else 'hidden')
    ).place(
        relx=0.5, rely=0.8, anchor=tk.CENTER
        )

root.mainloop()

Upvotes: 1

Related Questions