конфликты между tkinter и pygame.midi - PullRequest
1 голос
/ 11 марта 2019

Я пытаюсь написать программу на Python 3, которая настраивает графический интерфейс пользователя с tkinter для отображения изображения (в метке) и установки ряда параметров с помощью различных виджетов.(Эта часть работает нормально.)

Я хочу, чтобы Gui оставался на экране, пока я выхожу и запускаю остальную часть программы, которая использует pygame.midi для ввода и вывода данных midi.(Он не использует pygame для представления каких-либо экранов.) (Эта часть также отлично работает сама по себе.)

Время от времени, при контроле того, что происходит в той части программы, которую я хочу обновитьGui и / или сбросить некоторые параметры, а затем вернуться к миди вещи.(Другими словами, я рад, что графический интерфейс пользователя неактивен, пока я не скажу ему проснуться.) Это не сработает.

Я попытался поместить команду mainloop () в конценастройка графического интерфейса.Я пытался разместить его в самом конце программы.ни один не работает.Мне кажется, что миди-опрос, который делает pygame.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 Ответ

1 голос
/ 27 марта 2019

Последний листинг кода включает в себя то, что я узнал.По сути, я не понимал того факта, что «переменные», упоминаемые во многих публикациях как обновляемые, на самом деле были переменными tkinter (StringVar, BooleanVar и т. Д.).Таким образом, переменные python необходимы для установки переменных tkinter.Я также подумал, что mainloop автоматически ищет изменения в переменных tkinter и обновляется автоматически.Другими словами, я не понимал, что мне нужно было установить «trace» для переменных, которые я хотел наблюдать.После этого мне нужно было узнать, что «трассировка» не обновляется автоматически, вы должны использовать ее, чтобы вызвать явное «обновление».В моем фактическом коде (слишком длинном, чтобы публиковать здесь) я использую переменные tkinter, «установленные» событиями midi, чтобы изменить выбор в списке (через «очистить», «активировать», «selection_set» и «посмотреть») и «обновить»"изображения, отображаемые в метке (которые связаны с индексом выбранного элемента).Насколько я могу судить, автоматически ничего не происходит.

...