Многопроцессорное рисование Python на холсте Tkinter - PullRequest
0 голосов
/ 26 июня 2018

У меня есть программа, которая использует несколько ядер для обработки изображений перед рисованием на холсте для основного вида (с использованием многопроцессорной обработки). Я хотел бы знать лучший способ решения этой проблемы.

Возможно ли, чтобы каждый базовый чертеж имел свой собственный холст, который наложен друг на друга в одном и том же виде? Возможно ли такое поведение?

1 Ответ

0 голосов
/ 26 июня 2018

Нет, это невозможно. GUI-виджеты не могут быть общими для процессов. На некоторых платформах это просто невозможно вообще; на других платформах это было бы возможно, но только если делать что-то совсем не так, как это делает Tk; на других это вроде работает, но все циклы событий облажались. Таким образом, результатом может быть то, что ничего не отображается, один или оба процесса зависают, графический интерфейс не реагирует на события, tkinter вызывает исключение в дочернем процессе, что tkinter создает целый отдельный независимый графический интерфейс, или, если вы действительно не повезло, что вещи непредсказуемо работают иногда, но делают другие вещи в другое время.


Однако это не значит, что нет способа делать то, что вы хотите, просто вы не можете сделать это напрямую.

Самое простое решение - собрать ваши Canvas команды и передать их через Pipe или Queue для выполнения основного процесса.

Полностью общее решение не так сложно, но в вашем случае оно должно быть еще проще: все, что вы хотите, чтобы фоновый процесс - это обрабатывает изображение и затем отображает его. Поэтому единственная команда Canvas, которая вам нужна, это create_image.

И, на самом деле, вы, вероятно, можете делать с задачами на Pool, который просто return изображение, когда они сделаны, с основным процессом, выполняющим create_image с результатами.

Смешивать ожидание при multiprocessing асинхронных результатах с циклом событий tkinter - это немного больно, но если вы используете concurrent.futures, вы можете просто присоединить create_image в качестве обратного вызова к Future, возвращаемому задача.


Другой вариант - заставить фоновые процессы создавать объекты вне экрана Canvas, рисовать их, а затем записывать результаты в виде BitmapImage или postscript рендеринга, который затем можно передать основному процессу. блин на Canvas своего. Но это намного сложнее; Я думаю, что другое решение, вероятно, будет работать намного лучше для вас.

...