«Независимый» запуск окна GUI - PullRequest
2 голосов
/ 08 июля 2010

Я довольно новичок в программировании с графическим интерфейсом и пытаюсь написать графическую библиотеку на D для использования с некоторыми другими консольными научными приложениями.Я использую DFL в качестве библиотеки GUI.

Предположим, что в моей форме графика есть метод showPlot(), который должен отображать график на экране.Мне бы хотелось, чтобы любой поток в моем приложении вызывал окно графика и либо блокировал, пока график не закрылся, либо продолжал работать, без вызова showPlot() необходимости знать, что любой другой поток делает с графикомили какие сюжеты были созданы в прошлом и все еще могут быть на экране.(Внутренние данные showPlot() могут, конечно, обладать этими знаниями.)

Я все еще пытаюсь обернуть голову, как обычно работают графические библиотеки под капотом.Кажется, у вас должен быть только один поток GUI и одна основная форма.Я был бы признателен за ответы на уровне шаблонов дизайна, не зависящих от языка / библиотеки, в дополнение к языку / библиотеке.

Редактировать: чтобы подчеркнуть, у этого приложения нет графического интерфейса, кроме графиков, которые оно выдает на интересномуказывает на его исполнение.Это в основном консольное приложение плюс несколько графиков.Следовательно, нет четко определенной «основной» формы.

Ответы [ 2 ]

2 голосов
/ 08 июля 2010

То, что вы собираетесь делать, скорее всего, будет зависеть от того, как работает DFL. Как правило, в приложении с графическим интерфейсом есть поток событий, который обрабатывает все события в вашем приложении - будь то перерисовывание событий, события нажатия кнопки, события нажатия мыши или что-то еще. Этот поток вызывает обработчик события, который зарегистрирован для обработки события (часто это виджет, по которому щелкнули или еще что-то). Проблема, с которой вы сталкиваетесь, заключается в том, что если вы попытаетесь сделать слишком много в этих обработчиках событий, вы заблокируете поток событий, чтобы другие события (включая события перерисовки) не обрабатывались своевременно. Некоторые наборы GUI даже специально ограничивают то, что вам разрешено делать в обработчике событий. Некоторые также ограничивают определенные типы операций этим конкретным потоком (например, выполнение чего-либо - особенно создание объекта - с фактическим GUI-кодом, таким как различные классы виджетов или окон, которые обязательно должен иметь инструментарий).

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

Как работают GUI, как правило, основано на событиях. Программа обрабатывает события от пользователя и системы и, как правило, не делает ничего, если не получает сигнал об этом. Зачастую приложения с графическим интерфейсом не делают ничего , пока им не сообщат о событии (хотя существует множество случаев, когда фоновый поток выполняет какую-то работу отдельно от событий). То, что вы пытаетесь сделать, не звучит особенно на основе событий, поэтому это немного усложняет ситуацию.

Полагаю, вам нужно, чтобы ваше приложение создавало новое окно каждый раз, когда вы хотите создать новый сюжет. Это окно, вероятно, будет дочерним окном главного окна, которое будет скрыто, поскольку оно вам явно не нужно, и, вероятно, DFL требует, чтобы у вас было какое-то главное окно. Есть хороший шанс, что каждый поток, который хочет создать окно, должен будет сказать этому главное окно графического интерфейса, но это зависит от DFL. Также возможно, что DFL позволяет любому потоку создавать новые элементы графического интерфейса (например, новое окно).

Несмотря на это, это почти наверняка будет основной поток событий, который фактически обрабатывает окно. Поток, который хочет создать окно и заполнить его, вероятно, должен будет создать окно (прямо или косвенно), а затем обновить состояние окна, обновив набор общих переменных, чтобы поток событий мог соответствующим образом перекрасить окно. , Самое большее, что исходный поток, вероятно, сделает на самом деле перерисовать окно, это отправить событие перерисовки в окно после того, как он обновил состояние общих переменных, которые содержат данные, необходимые для рисования окна. Это не справится с самой картиной.

Что касается блокировки потока, то он, вероятно, должен был бы выполнить занятое ожидание, пока поток события не получит событие закрытия окна, и некоторая общая переменная не будет обновлена, или вы можете заставить его перейти в спящий режим, пока поток события не проснется это после получения события закрытия окна. В случае, если вы не хотите, чтобы он блокировался, ему просто не нужно ждать, пока ему сообщат о событии с закрытыми окнами, и он будет продолжать пыхтеть.

В любом случае, надеюсь, этой информации достаточно, чтобы направить вас в правильном направлении. Обычно события управляют всем, все, так сказать, за пределами графического интерфейса. Но в вашем случае ваше приложение использует графический интерфейс, больше похожий на стандартный вывод. Таким образом, вы могли бы лучше сначала поработать над некоторыми небольшими, довольно глупыми приложениями с графическим интерфейсом, которые являются реальными, обычными приложениями с графическим интерфейсом на основе событий (например, игра в крестики-нолики или что-то в этом роде), чтобы лучше понять, как GUI работает, прежде чем пытаться заставить его работать несколько менее стандартным способом, чем вы.

0 голосов
/ 08 июля 2010

Каркасы GUI обычно имеют свой собственный цикл обработки событий и вызывают код приложения как обратные вызовы в ответ на внешние события (нажатия кнопок, таймеры, перерисовка, ...). Основное различие между «типичным» консольным приложением и приложением с графическим интерфейсом состоит в том, что вы отказываетесь от управления вызовом функции в инфраструктуре графического интерфейса пользователя.

Потоки обычно используются, когда код приложения содержит какой-то длительный процесс, который нельзя прервать на более мелкие фрагменты (большие вычисления, копирование файлов, контроль над миром, ...). Затем используется один поток, чтобы поддерживать отзывчивость GUI, а работа выполняется в отдельном потоке. Основная проблема состоит в том, чтобы поддерживать правильность синхронизации обоих потоков, так как большинство инструментов GUI не способны обрабатывать вызовы из более чем одного потока. Если у вас есть только небольшие рабочие части, которые не блокируют графический интерфейс в течение длительного времени (<0,1 с), тогда лучше остаться без рабочих потоков. </p>

Я также настоятельно рекомендую отделить код GUI и логику приложения друг от друга. Смешанный код GUI и код приложения - это кошмар обслуживания.

...