Добро пожаловать в чудесный мир блокированного диспетчеризации событий (и нарушение первоначального потока)
По сути, Swing - это единая резьбовая среда, все обновления и модификации для пользовательского интерфейса должны быть выполнены в контексте потока диспетчеризации событий (он же EDT).
EDT несет ответственность, среди прочего, обработку запросов на перекрашение. Если по какой -то причине вы блокируете этот поток (например, используя длинный цикл или блокировку io), это не позволит EDT обрабатывать новые запросы на краску, что сделает ее, как будто ваша программа висела ... потому что, по сути, это имеет.
Причина, по которой вы можете увидеть разницу между бегом Timer
непосредственно и использует его в вашем графическом интерфейсе, потому что, когда приложение запускается, оно будет работать внутри, что обычно известно как «основная» поток.
Когда вы сначала создаете контейнер для качания на верхнем уровне, запускается EDT (который является отдельным потоком), что означает, что пользовательский интерфейс появится в собственном потоке, но приложение будет продолжать работать в «основном» потоке, позволяя вашему iterate
Метод запуска независимо от EDT.
Однако, когда вы пытаетесь запустить его из своего графического интерфейса, все это работает в контексте EDT, заставляя его заблокировать.
Начните с взгляда на
Чтобы решить проблему, основываясь на вашем примере кода, я бы предложил использовать SwingWorker
. Анкет Это позволит вам запустить «давнюю задачу» в фоновом потоке, но предоставит ряд методов, которые позволяют вам восстановить обновления обратно в EDT. Это очень важно, так как вы никогда не должны пытаться обновлять пользовательский интерфейс или изменять его состояние из любого потока, кроме EDT.
Взгляни на Рабочие нити и качание Больше подробностей
И, если требуется, некоторые примеры ...