繁体   English   中英

tkinter 和 pygame.midi 之间的冲突

[英]conflicts between tkinter and 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()

最后一个代码清单包含了我学到的东西。 基本上我不明白在许多帖子中提到的“变量”被更新的事实,实际上是 tkinter 变量(StringVar、BooleanVar 等)。 所以python变量需要设置tkinter变量。 我还认为 mainloop 会自动查找 tkinter 变量中的更改并自动更新。 换句话说,我不明白我需要为我想观察的变量设置“跟踪”。 在那之后,我需要了解“跟踪”不会自动更新,您必须使用它来触发显式“更新”。 在我的实际代码(太长,无法在此处发布)中,我使用 tkinter 变量通过 MIDI 事件“设置”来更改列表框中的选择(通过“清除”、“激活”、“selection_set”和“查看”)和“更新” " 显示在标签中的图像(链接到所选项目的索引)。 据我所知,没有任何事情会自动发生。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM