【问题标题】:Trying to make a stoplight that changes colour depending on sound (loud sound = red, normal sound = green etc)尝试制作一个根据声音改变颜色的红绿灯(响亮的声音=红色,正常的声音=绿色等)
【发布时间】:2019-06-25 08:55:06
【问题描述】:

我一直在尝试制作一个 Tkinter 应用程序,作为所产生声音的反馈信号灯。因此,例如,当它在图书馆里响亮时,你会得到一个红灯,但当它正常时,它会变成绿色等等。

基本上,我已经创建了一个带有画布的 Tkinter 应用程序,并在一个矩形中制作了 3 个圆圈(红绿灯),还创建了一个函数来从你的麦克风获取输入以查看声音的高低。

此代码在一个单独的文件中用于获取输入声音:

def decide_colour():

    def print_sound(indata, outdata, frames,tijd, status):
        global colour
        volume_norm = np.linalg.norm(indata)
        print(volume_norm)
        time.sleep(1)

        #set fill colour
        if volume_norm > 2 and volume_norm <4:
            colour = "yellow"
        elif volume_norm > 4:
            colour = "red"
        else:
            colour = "green"

        print(colour)

    with sd.Stream(callback=print_sound):
        sd.sleep(duration * 1000)


decide_colour()

这是应该显示它的 tkinter 应用程序:

class TrafficLights:

    def __init__(self):

        root = Tk()
        root.title("Stoplicht")
        root.configure(bg='black')
        root.geometry('460x400')

        # Frame voor widgets
        frame = Frame(root)
        frame.grid()

        self.colour = StringVar()

        # canvas voor lichten
        self.canvas = Canvas(root, width=460, height=400, bg="black")
        self.canvas.create_rectangle(190, 10, 310, 350, outline='white', fill='black')
        self.canvas.grid()

        self.oval_red = self.canvas.create_oval(200, 20, 300, 120, fill="white")

        self.oval_yellow = self.canvas.create_oval(200, 130, 300, 230, fill="white")

        self.oval_green = self.canvas.create_oval(200, 240, 300, 340, fill="white")

        # kleurbepaling voor de cirkels
        def change_color(self):

            if colour == 'red':
                self.canvas.itemconfig(self.oval_red, fill="red")
                self.canvas.itemconfig(self.oval_yellow, fill="white")
                self.canvas.itemconfig(self.oval_green, fill="white")
            elif colour == 'yellow':
                self.canvas.itemconfig(self.oval_red, fill="white")
                self.canvas.itemconfig(self.oval_yellow, fill="yellow")
                self.canvas.itemconfig(self.oval_green, fill="white")
            elif colour == 'green':
                self.canvas.itemconfig(self.oval_red, fill="white")
                self.canvas.itemconfig(self.oval_yellow, fill="white")
                self.canvas.itemconfig(self.oval_green, fill="green")

        change_color(self)

        root.after(500, change_color(self))
        #root.after(500, TrafficLights)

        root.mainloop()


while True:
    decide_colour()
    TrafficLights()

但它陷入了一个循环。并且通过摆脱while 语句,它只会打开一次。但我希望它继续运行,我希望它改变红绿灯的颜色。我已经尝试了几天,寻找答案。但我现在真的被困住了。

【问题讨论】:

  • decide_colour() 中使用的sd 是什么?一个(但不是唯一)错误是 root.after(500, change_color(self)) 调用,应该写成 root.after(500, change_color, self)
  • sd是sounddevice的,每秒返回声音的值,
  • 好的,但是为了给您提供一个体面的答案,我仍然需要了解您的代码在哪些方面做得更好。 with sd.Stream(callback=print_sound): 和关注 sd.sleep(duration * 1000) 是如何工作的?这是允许重写(或替换)decide_colour() 的必要条件。
  • 我将 sounddevice 作为 sd 导入,所以 sd.stream(callback=print_sound): 将我的麦克风的输入打印到控制台,sd.sleep(duration*1000) 是多长时间运行
  • 对不起,但这并不能描述我想知道的内容。 callback= 参数的作用是什么,为什么 sd.sleep(duration * 1000)with 语句中?

标签: python loops canvas tkinter real-time


【解决方案1】:

问题似乎与您的程序的组织有关。不需要while 循环。我做了一个简单的例子来说明after 应该如何工作。在after 循环中调用的函数应该从decide_colour() 函数中获取它需要的数据。在此示例中,它将是 my_count()

from tkinter import *

class Counter(Frame):

    def __init__(self, master=None):
        self.count = 0
        super().__init__(master)
        self.grid()
        self.__create_widgets()

    def __create_widgets(self):
        self.count_label         = Label(self)
        self.count_label["text"] = str(self.count)
        self.count_label["pady"] = 5
        self.count_label.grid()


    def my_count(self):
        self.count = self.count+1
        self.count_label["text"] = str(self.count)


root = Tk()
counter = Counter(master=root)

#do you app set up here
root.title("Counter")
root.geometry('460x400')

def do_one_iteration():
    counter.my_count()
    root.after(500, do_one_iteration)
do_one_iteration()

counter.mainloop()

【讨论】:

  • 你的回答绝对有帮助,虽然我不确定如何在我的代码中使用它,但我找到了一种方法,但它不像你的
【解决方案2】:

好吧,这不是我想要的答案,但它仍然是一个答案

我将代码放在一起,并进行了一些调整。

from tkinter import *
import sounddevice as sd
import numpy as np
import time

duration = 1  #


def decide_colour():
    def print_sound(indata, outdata, frames, tijd, status):
        global colour
        volume_norm = np.linalg.norm(indata)
        time.sleep(1)

        # set fill colour
        if 2 < volume_norm < 4:
            colour = "yellow"
        elif volume_norm > 4:
            colour = "red"
        else:
            colour = "green"

        print(volume_norm, colour)

    with sd.Stream(callback=print_sound):
        sd.sleep(duration * 1000)


class TrafficLights:

    def __init__(self):

        root = Tk()
        root.title("Stoplicht")
        root.configure(bg='black')
        root.geometry('460x400')

        # Frame voor widgets
        frame = Frame(root)
        frame.grid()

        self.colour = StringVar()

        # canvas voor lichten
        self.canvas = Canvas(root, width=460, height=400, bg="black")
        self.canvas.create_rectangle(190, 10, 310, 350, outline='white', fill='black')
        self.canvas.grid()

        self.oval_red = self.canvas.create_oval(200, 20, 300, 120, fill="red")
        self.oval_yellow = self.canvas.create_oval(200, 130, 300, 230, fill="white")
        self.oval_green = self.canvas.create_oval(200, 240, 300, 340, fill="white")

    def create_frame():
        decide_colour()

        if colour == 'red':
            self.canvas.itemconfig(self.oval_red, fill="red")
            self.canvas.itemconfig(self.oval_yellow, fill="white")
            self.canvas.itemconfig(self.oval_green, fill="white")
        elif colour == 'yellow':
            self.canvas.itemconfig(self.oval_red, fill="white")
            self.canvas.itemconfig(self.oval_yellow, fill="yellow")
            self.canvas.itemconfig(self.oval_green, fill="white")
        elif colour == 'green':
            self.canvas.itemconfig(self.oval_red, fill="white")
            self.canvas.itemconfig(self.oval_yellow, fill="white")
            self.canvas.itemconfig(self.oval_green, fill="green")

        create_frame()

        root.update()
        time.sleep(1)
        root.destroy()
        return


while True:
    TrafficLights()

所以现在它在一秒钟后打开一个新的主循环并破坏之前的主循环。我实际上希望它在一个主循环中更新,但不知道如何,所以如果有人知道请告诉我

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-09-19
    • 1970-01-01
    • 2021-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-31
    • 2017-05-28
    相关资源
    最近更新 更多