«Инициализировано» не обязательно совпадает с «Населенный». «Инициализировано» обычно означает, что объект полностью сконструирован, но может не иметь никаких данных. «Населенный», конечно, означает, что данные присутствуют и все задачи сбора данных завершены. Таким образом, можно предоставить вашей сторонней библиотеке полностью инициализированный JDialog без каких-либо данных.
Способ, которым я всегда хотел решить эту проблему, заключается в создании настраиваемого JDialog, который отображает сообщение занятости или индикатор выполнения или тому подобное, а затем запрашивает данные в другом потоке. Когда данные возвращаются, я заменяю сообщение «занято» данными (на EDT!). Что касается того, как вы должны выполнять свой запрос в фоновом потоке, я рекомендую использовать SwingWorkers. Мне нравится использовать приватный SwingWorker
внутри моего настраиваемого JDialog, который обрабатывает запрос в методе doInBackground()
и обрабатывает связанные с Display задачи в методе done()
. Выполнение этого способа гарантирует, что связанные с отображением задачи будут выполняться только в EDT, а задачи, связанные с базой данных, будут выполняться только с помощью EDT. Если вы хотите получить достаточно хорошее представление об использовании SwingWorkers, ознакомьтесь с Sun's tutorial on worker threads. Простой пример был бы:
public class DBDIalog extends JDialog{
private JLabel busyLabel = new JLabel("Fetching data from DataBase");
public DBDialog(){
//do your initialization stuff here
}
private class DBFetcher extends SwingWorker<Void,DBInfo>{
@Override
protected DBInfo doInBackground() throws Exception{
return fetchDataFromDB(); //or whatever database call to make
}
@Override
protected void done(){
try{
DBInfo info = get();
//replace your busy label with your DBInfo
}catch(InterruptedException e){
//do appropriate thread interrupted stuff
}catch(ExecutionException e){
//do appropriate general error handling stuff
}
}
}
}
Несколько вещей, чтобы помнить, хотя: метод done()
не является абстрактным, так что вы не обязаны переопределить его. Вы должны, однако. Если ваша реализация doInBackground()
вызывает исключение, это исключение будет проглочено, если только done()
не было отменено. Кроме того, не вносите изменений в свой графический интерфейс изнутри doInBackground()
, если вы не используете SwingUtilities.invokeLater(Runnable)
, так как doInBackground()
выполняется из другого потока, кроме EDT, и изменения графического интерфейса пользователя из фонового потока запрашивают странные и необъяснимые ошибки.
Когда это следует использовать? В отличие от других задач программирования, точка, в которой что-то слишком долго реагирует, намного короче в графических интерфейсах. Число, которое я обычно видел, записано около 250 мс. Если ваша задача занимает больше времени, она должна быть в фоновом потоке. В вашем случае, 10 секунд должны определенно быть в фоновом потоке, но тогда вы уже знали, что :)
EDIT:
Видя ваш комментарий, я вижу, что большая часть моего поста довольно спорный вопрос.Тем не менее, вы все равно можете использовать SwingWorker:
Попросите SwingWorker выполнить извлечение данных, а в методе done()
постройте JDialog из данных и передайте это диалоговое окно в свою стороннюю библиотеку.
Эта последняя часть о том, «что она построила JDialog из данных, а рука, что диалог ...» - это то, что сложно. Если мой метод вызывается в EDT, как я могу запустить что-то в фоновом режиме, а затем ждать его возвращения (чтобы я мог конструировать и возвращать диалог), не блокируя другие события, размещенные на EDT между тем, когда я вызываюсь и когда я вернусь? Похоже, что SwingWorker этого не решает. Тем не менее, ваши ответы были лучше из двух ответов. –
Вы можете переопределить 'process()' для отображения промежуточных результатов и/или вызвать 'setProgress()' по мере необходимости. Вот пример: http://sites.google.com/site/drjohnbmatthews/randomdata – trashgod