I am trying to make a model of piano with actual piano sounds and Tkinter GUI interface, but I am not able to use threading to use a particular function that requires input from the user.
When I tried to initiate threading in the init () method of the piano class it asks for 1 positional argument which I want to pass after the user inputs through Tkinter button, but cannot write the threading function in the proper way. Kindly provide me a solution, that would be a great help.
I am linking my code and screenshot along with this for reference.
# importing necessary libraries
from tkinter import *
import playsound
import threading
import os
# folder path declaration
folder_path = r'E:\\Programming\\python_practice\\music_notes'
# Music note declaration
noteList = [] # empty list to store music notes as list elements
def listDir(dir): # get notes from the path and put into the list
fileNames = os.listdir(dir)
for fileName in fileNames:
noteList.append(fileName)
listDir(folder_path)
# Creating the temporary tkinter windows which will later be replaced with RbPi button interface
root = Tk()
root.title("Python Piano")
# Creating empty file-list
files =[]
# Adding note to empty file-list
for i in range(len(noteList)):
files.append(str(i))
# Creating empty button-list
btns = []
# Creating Piano Class
class Piano:
def __init__(self,master):
# Declaring frame an creating a Frame
global myFrame
myFrame = Frame(master)
myFrame.pack()
# Creating a thread for asynchronous playing of same or individual notes
# -------- C O D E ---------
# Create Buttons and assing individual notes to each button
def buttonGenerator(self):
for i in range(len(files)):
btns.append(Button(myFrame, text=files[i], padx=20, pady=60, command = lambda t = i:self.playNotes(t)))
btns[i].grid(column=[i], row=0)
# Play notes of each button
def playNotes(self,note):
playsound.playsound(folder_path + "\\" + noteList[note])
# Creating an instance of Piano class
myPiano = Piano(root)
# Calling inner method of the Piano class
myPiano.buttonGenerator()
# Looping through the program
root.mainloop()
Here's the basic concept. I haven't tested this, because I don't have your sounds, but I made several changes.
Eventually, you will not want to play sound files to do this. That's too slow. You will probably want to use MIDI to send notes to your system's synthesizer.
# importing necessary libraries
import os
from tkinter import *
import playsound
import threading
import queue
# folder path declaration
folder_path = r'E:\\Programming\\python_practice\\music_notes'
# Music note declaration
def listDir(dir): # get notes from the path and put into the list
return os.listdir(dir)
noteList = listDir(folder_path)
# Creating the temporary tkinter windows which will later be replaced with RbPi button interface
root = Tk()
root.title("Python Piano")
# Creating Piano Class
class Piano(Frame):
def __init__(self,master):
super().__init__(master)
self.pack()
self.queue = queue.Queue()
self.btns = []
# Creating a thread for asynchronous playing of same or individual notes
# -------- C O D E ---------
threading.Thread( target = self.playNotes ).start()
# Create Buttons and assing individual notes to each button
def buttonGenerator(self):
for i in range(len(files)):
self.btns.append(Button(self, text=str(i), padx=20, pady=60, command = lambda t = i:self.playNote(t)))
self.btns[-1].grid(column=[i], row=0)
def playNote(self,n):
self.queue.put( n )
# Play notes of each button
def playNotes(self):
while True:
item = self.queue.get()
if item == 'exit':
return
playsound.playsound(folder_path + "\\" + noteList[item])
# Creating an instance of Piano class
myPiano = Piano(root)
# Calling inner method of the Piano class
myPiano.buttonGenerator()
# Looping through the program
root.mainloop()
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.