Как создать автоматически заполняемую прокручивающуюся сетку кадров (tkinter)? - PullRequest
0 голосов
/ 13 июля 2020

Я пытаюсь создать скользящую сетку кадров. У меня будет переменное количество кадров, поэтому я хочу указать количество столбцов, но не количество строк, хотя мы можем прокрутить вниз, если оно будет слишком длинным.

Я написал код, но теперь я не знаю, как указать, что при создании рамки (кнопка + 2 шкалы) с помощью sound_buttons () она принадлежит определенной строке и определенному столбцу. Кроме того, у меня не всегда будет число кадров, кратное 5, поэтому последняя строка может состоять только из 1, 2, 3 или 4 кадров.

Целью было бы иметь что-то вроде это, но с неопределенным количеством строк: tkinter Canvas Scrollbar с сеткой? .

Большое спасибо!

#!/usr/bin/env python3
# -*- coding:utf-8 -*-

# -------------------------------- Importation ------------------------------- #

import tkinter as tk
from tkinter import messagebox

# ------------------------------ Initialisation ------------------------------ #

root = tk.Tk()

width_screen, height_screen = root.winfo_screenwidth(), root.winfo_screenheight()
root.geometry("%dx%d+0+0" % (width_screen, height_screen))



# ----------------------- Creation of a list of sounds ----------------------- #

wav_files = ["a.wav","b.wav","c.wav","d.wav","e.wav","f.wav","g.wav","h.wav","i.wav","j.wav","k.wav","l.wav","m.wav","n.wav","o.wav","p.wav","q.wav","r.wav","s.wav","t.wav","u.wav","v.wav","w.wav","x.wav","y.wav","z.wav","aa.wav","bb.wav","cc.wav","dd.wav","ee.wav","ff.wav"]

# -------------------------- Vertical scrolled frame ------------------------- #

class VerticalScrolledFrame(tk.Frame):

    def __init__(self, parent, *args, **kw):
        tk.Frame.__init__(self, parent, *args, **kw)            

        # Create a frame for the canvas with non-zero row&column weights
        self.frame_canvas = tk.Frame(self)
        self.frame_canvas.grid(row=2, column=0, pady=(8, 0), sticky='nw')
        self.frame_canvas.grid_rowconfigure(0, weight=1)
        self.frame_canvas.grid_columnconfigure(0, weight=1)
        # Set grid_propagate to False to allow buttons resizing later
        self.frame_canvas.grid_propagate(False)

        # create a canvas object and a vertical scrollbar for scrolling it
        vscrollbar = tk.Scrollbar(self.frame_canvas, orient=tk.VERTICAL)
        vscrollbar.grid(row=0, column=1, sticky='ns')
        self.canvas = tk.Canvas(self.frame_canvas, bd=0, highlightthickness=0,
                        yscrollcommand=vscrollbar.set, width=root.winfo_screenwidth(), height=root.winfo_screenheight())
        self.canvas.grid(row=0, column=0, sticky="news")
        vscrollbar.config(command=self.canvas.yview)
        
        self.canvas.bind_all("<MouseWheel>", self._on_mousewheel)
        
        # reset the view
        #canvas.xview_moveto(0)
        #canvas.yview_moveto(0)

        # create a frame inside the canvas which will be scrolled with it
        self.interior = interior = tk.Frame(self.canvas)
        interior_id = self.canvas.create_window(0, 0, window=interior,
                                           anchor=tk.NW)
        self.interior.update_idletasks()

        # track changes to the canvas and frame width and sync them,
        # also updating the scrollbar
        def _configure_interior(event):
            # update the scrollbars to match the size of the inner frame
            size = (interior.winfo_reqwidth(), interior.winfo_reqheight())
            self.canvas.config(scrollregion="0 0 %s %s" % size)
            if interior.winfo_reqwidth() != self.canvas.winfo_width():
                # update the canvas's width to fit the inner frame
                self.canvas.config(width=interior.winfo_reqwidth())

        interior.bind('<Configure>', _configure_interior)

        def _configure_canvas(event):
            if interior.winfo_reqwidth() != self.canvas.winfo_width():
                # update the inner frame's width to fill the canvas
                self.canvas.itemconfigure(interior_id, width=self.canvas.winfo_width())
        self.canvas.bind('<Configure>', _configure_canvas)

    def _on_mousewheel(self, event):
        self.canvas.yview_scroll(int(-1*(event.delta/120)), "units")


# ------------------------------- Sound buttons ------------------------------ #


class Make_sound:
    def __init__(self, name, parent):
        self.varbutton = tk.StringVar()
        self.name = name
        self.parent = parent

        self.soundbuttoncreator()


    def launchsound(self):
        print(self.varbutton.get())
        if self.varbutton.get() == 1:
            self.list=[]
        else:
            self.list.append("A")

    def soundbuttoncreator(self):
        self.frame = tk.Frame(self.parent) # create a frame to hold the widgets
        
        # use self.frame as parent instead of self.parent
        self.volumescale = tk.Scale(self.frame, orient='vertical', from_=100, to=0, resolution=0.5, label='Volume',command=self.setvolume, cursor="fleur")
        self.volumescale.grid(row=0,column=1, rowspan=2, sticky="nsew")
        self.volumescale.set(100)
        
        self.faderscale = tk.Scale(self.frame, orient='horizontal', from_=-1, to=1, resolution=0.01, label='Balance G/D', command=self.setbalance, cursor="fleur")
        self.faderscale.grid(row=1,column=0, sticky="nsew")
        
        self.button = tk.Checkbutton(self.frame, text=self.name, indicatoron=False, selectcolor="green", background="red", variable=self.varbutton, command=self.launchsound, cursor="plus") 
        self.button.grid(row=0, column=0, sticky="nsew")

        self.frame.pack()  # use pack() on the frame so new instance of `Make_sound` will not overlap the old instances

    def setvolume(self,event):
        pass

    def setbalance(self,event):
        pass


def sounds_buttons(parent):
    for i in range(len(wav_files)):
        new_name = wav_files[i][:-4]
        globals()["wav_files"][i] = Make_sound(new_name,parent)

# ---------------------------------------------------------------------------- #
#                                   Creation                                   #
# ---------------------------------------------------------------------------- #

# ----------------------------- Buttons of sound ----------------------------- #

scframe = VerticalScrolledFrame(root)
scframe.pack(side=tk.LEFT)

sounds_buttons(scframe.interior)

root.mainloop()

РЕДАКТИРОВАТЬ 1: Я изменил Класс Make_sound и функция Sound_buttons. Произошла ошибка.

class Make_sound:
    def __init__(self, name, parent, i):

        self.varbutton = tk.StringVar()

        self.name = name
        self.parent = parent
        self.num = i
        self.soundbuttoncreator()

    def launchsound(self):
        print(self.varbutton.get())
        if self.varbutton.get() == 1:
            self.list=[]
        else:
            self.list.append("A")

    def soundbuttoncreator(self):

        self.rows = self.num//5
        self.columns = self.num%5

        self.frame = tk.Frame(self.parent) # create a frame to hold the widgets
        
        # use self.frame as parent instead of self.parent
        self.volumescale = tk.Scale(self.frame, orient='vertical', from_=100, to=0, resolution=0.5, label='Volume',command=self.setvolume, cursor="fleur")
        self.volumescale.grid(row=0,column=1, rowspan=2, sticky="nsew")
        self.volumescale.set(100)
        
        self.faderscale = tk.Scale(self.frame, orient='horizontal', from_=-1, to=1, resolution=0.01, label='Balance G/D', command=self.setbalance, cursor="fleur")
        self.faderscale.grid(row=1,column=0, sticky="nsew")
        
        self.button = tk.Checkbutton(self.frame, text=self.name, indicatoron=False, selectcolor="green", background="red", variable=self.varbutton, command=self.launchsound, cursor="plus") 
        self.button.grid(row=0, column=0, sticky="nsew")

        self.frame.grid(row=self.rows, column=self.columns)

    def setvolume(self,event):
        pass

    def setbalance(self,event):
        pass

def sounds_buttons(parent):
    for i in range(len(wav_files)):
        new_name = wav_files[i][:-4]
        globals()["wav_files"][i] = Make_sound(new_name,parent,i)
...