Ответ, я думаю, будет после того, как все начальные размеры компонентов будут выполнены, но взгляните на этот SSCCE:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Test2 {
private static void createAndShowGUI2() {
final JFrame frame = new JFrame("Test2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton addSecondListener = new JButton("Click me to add a second listener");
addSecondListener.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
System.out.println("Component Listener 2");
}
});
}
});
frame.getContentPane().add(addSecondListener);
frame.setSize(200, 200);
frame.setVisible(true);
frame.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
System.out.println("Component Listener 1");
//throw new NullPointerException("Just getting traceback...");
}
});
}
public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI2();
}
});
}
}
Несмотря на то, что Component Listener 1 добавляется после изменения размера кадра и его отображения, событие изменения размера вызывается при запуске java Test2
; он напечатает Component Listener 1
первым делом.
Первоначально это привело меня к мысли, что добавление прослушивателя компонента всегда будет вызывать событие изменения размера сразу после этого. Однако, это не так. Если вы нажмете кнопку JButton внутри фрейма, будет добавлен слушатель компонента 2, и вы не увидите его печать Component Listener 2
так, как вы, вместо этого он сработает только при изменении размера фрейма.
Что заставляет прослушиватель компонента срабатывать после того, как размер кадра был изменен, прежде чем он даже стал видимым? Я бросил там исключение, чтобы увидеть, что трассировка (в настоящее время закомментирована), чтобы дать мне несколько подсказок:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException: Just getting traceback...
at Test2$2.componentResized(Test2.java:31)
at java.awt.Component.processComponentEvent(Component.java:5960)
at java.awt.Component.processEvent(Component.java:5914)
at java.awt.Container.processEvent(Container.java:2023)
at java.awt.Window.processEvent(Window.java:1816)
at java.awt.Component.dispatchEventImpl(Component.java:4501)
at java.awt.Container.dispatchEventImpl(Container.java:2081)
at java.awt.Window.dispatchEventImpl(Window.java:2458)
at java.awt.Component.dispatchEvent(Component.java:4331)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Для моего приложения я хочу добавить ComponentListener после того, как все начальные размеры будут установлены программно без запуска componentResized (пока пользователь фактически не изменит размер фрейма/компонента). Как я могу это сделать?
Редактировать: я знаю, что есть способы обойти это, например, добавить логическое значение, которое изначально является ложным, а затем установлено, чтобы игнорировать первое событие изменения размера. Однако это не кажется мне сверхнадежным, и я просто хочу знать, что происходит.