Графические интерфейсы Java, JFrames и диалоги

Я читал, что вы не должны .show() кадры в основном потоке, чтобы избежать взаимоблокировки, это реальная проблема. Всегда ли этого следует избегать? Кроме того, когда вы отображаете любое диалоговое окно, такое как ProgressMonitorInputStream, даже если оно закрывается и выполняется, должны ли вы по-прежнему вызывать System.exit(), чтобы убить приложение? Как насчет JDialog?


person rubixibuc    schedule 29.08.2012    source источник
comment
Я читал, что вы не должны .show() кадры.. Начиная с 1.5 мы должны setVisible(true).   -  person Andrew Thompson    schedule 30.08.2012


Ответы (2)


Я читал, что вы не должны использовать кадры .show() в основном потоке, чтобы избежать взаимоблокировки.

Он перестанет читать эту книгу/пост/веб-страницу.

Чтобы ответить на ваш первый вопрос:

Я думаю, что вы можете упустить некоторые моменты.

Весь код пользовательского интерфейса ДОЛЖЕН выполняться в диспетчере событий. Поток (EDT) включает компоненты пользовательского интерфейса, которые еще даже не отображаются на экране.

Вы должны НЕ выполнять трудоемкие задачи во время EDT, так как это предотвратит обновление экрана и сделает ваше приложение неотзывчивым, что пользователи очень и очень ненавидят.

Трудоемкие задачи должны выполняться в собственном потоке (на самом деле это совершенно другая тема), используя что-то вроде SwingWorker или SwingUtilities.invokeLater/andWait для повторной синхронизации/обновления пользовательского интерфейса.

public class BackgroundTask implements Runnable { // extends Thread {

    public void run() {
        for (int i = 0; i < noQueries; i++) {
            runDatabaseQuery(i);
            updateProgress(i);
        }
    }

    private void updateProgress(final int queryNo) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                statusLabel.setText("Query: " + queryNo);
            }
        });
    }
}

Чтобы решить ваш второй вопрос:

Да и нет. Класс JFrame предоставляет defaultCloseOperation, который вы можете использовать для завершения основного приложения.

Однако, если все, что вы когда-либо отображали, это JDialog или окно другого типа, да, вам нужно будет вызвать System.exit, чтобы завершить работу JVM.

Там, где это поддерживается, вы можете использовать WindowListener.windowClosed для отслеживания закрытия окна и выполнения соответствующих действий.

person MadProgrammer    schedule 29.08.2012
comment
Чтобы улучшить свой ответ, вы можете добавить пример SwingUtilities.invokeLater() и invokeAndWait() :) - person zip; 29.08.2012
comment
@zip Ты трудный мастер, мой друг ;) - person MadProgrammer; 29.08.2012
comment
Итак, я должен вызвать show() на EDT? Даже если он просто отображает кадр? А можно и саму рамку отображать? - person rubixibuc; 29.08.2012
comment
Будет ли безопасным отображение фрейма в его конструкторе? - person rubixibuc; 29.08.2012
comment
Пока конструктор вызывается из EDT. Вы можете проверить, используя EventQueue .isDispatchThread - person MadProgrammer; 29.08.2012
comment
Если вы действительно хотите, вы можете прочитать треды и свинг - person MadProgrammer; 29.08.2012
comment
В некотором смысле, invokeLater / invokeAndWait являются противоположностями SwingWorker (один используется для выполнения в EDT, другой - нет) - это кажется затушеванным в тексте. Еще +1. - person Jacob Raihle; 29.08.2012
comment
Возможно, я придираюсь к нику, но я бы сказал, что один из них МОЖЕТ быть выполнен в EDT (invokeLater), а оба могут быть вызваны вне EDT. Основное преимущество invokeAndWait заключается в том, что он способен возвращать значение (и приостанавливать работающий поток до тех пор, пока он не вернется), но, по сути, мы говорим одно и то же. - person MadProgrammer; 29.08.2012

Закрытие основного JFrame в приложении должно вызывать System.exit(); Однако вы можете заставить главное JFrame закрыть само приложение:

setDefaultCloseOperation(EXIT_ON_CLOSE);

Модальные JDialog блокируют поток, из которого они вызываются. Однако в этом есть преимущества. Когда вы зависите от ответа пользователя в JDialog для выполнения действия, вы должны дождаться этого.

person Dan D.    schedule 29.08.2012
comment
setDefaultCloseOperation(EXIT_ON_CLOSE); Лучше использовать DISPOSE_ON_CLOSE. - person Andrew Thompson; 29.08.2012
comment
Да, в зависимости от того, каким вы хотите видеть поведение приложения. Если это основной фрейм и вы хотите выйти из приложения, не запрашивая у пользователя сохранения данных приложения, вы можете использовать EXIT. - person Dan D.; 29.08.2012
comment
В этом конкретном случае вы можете использовать DISPOSE. Кстати, приложение должно иметь только один кадр. - person Andrew Thompson; 30.08.2012