tkinter和pygame.midi之间的冲突

时间:2019-03-11 14:22:32

标签: python tkinter pygame midi

我正在尝试编写一个Python 3程序,该程序使用tkinter设置Gui来显示图像(在标签中) 并通过各种小部件设置许多参数。 (这部分工作正常。)

我想让Gui在我离开并运行使用pygame.midi的程序的其余部分时留在屏幕上 输入和输出MIDI数据。 (它不使用pygame来显示任何屏幕。)(这部分在其上也可以正常工作 自己的。)

我不时要控制程序那部分中发生的事情,以便更新Gui和/或重置 一些参数,然后再回到midi的东西。 (换句话说,我很高兴让gui lie处于休眠状态,直到我 告诉它醒来。)它将不起作用。

我尝试将mainloop()命令放在gui设置的末尾。我尝试将其放在程序的最后。 都不起作用。在我看来,不允许pygame.midi进行的midi轮询是因为gui和midi 轮询涉及冲突线程。我对么?有没有简单的解决方案?您能指出我可能找到的地方吗?

已添加代码:


    #!/usr/local/bin/python3

from tkinter import Tk
from tkinter import ttk
from tkinter import Frame
from tkinter import E, W
from tkinter import StringVar

import sys
import os

import pygame.midi


def do_nothing(*args):
    labelbox.update()


def do_midi():
    global pygame_initialized, midi_out, midi_in, msgVar
    if not pygame_initialized:
        pygame.init()
        pygame.midi.init()  # Sets PortMidi timer to zero.
        midi_in = pygame.midi.Input(3, 4096)
        midi_out = pygame.midi.Output(2)
        pygame_initialized = True

    midi_out.write_short(176, 122, 00)  # turn off echo
    while True:
        if midi_in.poll():
            midi_event_list = midi_in.read(1)
            event = midi_event_list[0][0][0]

            if event == 248:  # timing event ignore
                continue

            if event > 159 or event < 128:  # non key-off or key-on midi events are passed through
                midi_out.write(midi_event_list)
                continue

            # From here on we are dealing only with key-on or key-off events

            key = midi_event_list[0][0][1]
            vel = midi_event_list[0][0][2]

            if key == 21:  # right now this is the only way back to the gui to Quit
                if vel != 0:
                    midi_out.write_short(176, 122, 127)  # Turn local control back on
                    return

            if vel != 0:  # only do this for key-on events
                msgVar.set(key)

            midi_out.write_short(event, key, vel)


def cleanup():
    global pygame_initialized, midi_out, midi_in
    root.destroy()
    if pygame_initialized:
        del midi_out
        del midi_in
        pygame.midi.quit()
    sys.exit()


if __name__ == '__main__':
    os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (0, 0)
    pygame_initialized = False
    global msgVar
    message = "Push the Play button!"

    root = Tk()

    msgVar = StringVar()
    msgVar.set(message)
    msgVar.trace("w", do_nothing)

    root.title("Testing midi")
    root.geometry("900x600+200+100")

    frame1 = Frame(root, width=900, height=600)
    frame1.grid(column=0, row=0)

    ttk.Button(frame1, text="Play", style='My.TButton', command=do_midi).grid(column=0, row=4, pady=(40, 0), sticky=W)
    labelbox = ttk.Label(frame1)
    labelbox.grid(column=1, row=4)
    labelbox.configure(textvariable=msgVar)


    ttk.Button(frame1, text="Quit", style='My.TButton', command=cleanup).grid(column=2, row=4, pady=(40, 0), sticky=E)

    root.mainloop()

1 个答案:

答案 0 :(得分:1)

最后的代码清单包含了我学到的东西。基本上,我不理解许多帖子中提到的“变量”实际上是更新的,它们是tkinter变量(StringVar,BooleanVar等)。因此,需要使用python变量来设置tkinter变量。我还认为mainloop会自动查找tkinter变量中的更改并自动更新。换句话说,我不明白我需要为想要监视的变量设置“跟踪”。之后,我需要了解“跟踪”不会自动更新,您必须使用它来触发显式的“更新”。 在我的实际代码中(太长,无法在此处发布),我正在使用midi事件的tkinter变量“ set”来更改列表框中的选择(通过“ clear”,“ activate”,“ selection_set”和“ see”)和“ update”标签中显示的图片(链接到所选项目的索引)。据我所知,什么也不会自动发生。