Когда getGraphics() вернет действительный экземпляр графики?

Я пытаюсь создать собственный компонент Swing, где я расширил класс JComponent.

В целях упрощения требований к компонентам давайте просто подытожим мой компонент как необходимый для отображения нескольких строк, каждый со своими собственными шрифтами.

Мне нужно, чтобы мой компонент был точно рассчитан на суммированную ширину и высоту отображаемых строк.

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

Проблема в том, что когда я обращаюсь к getGraphics(), он всегда равен нулю, поэтому я не могу получить экземпляр FontMetrics. Если я ожидаю, чтобы вычислить размер моего компонента из метода overriden paintComponent(), его довольно поздно (компонент уже имеет размер, правильно?).

В документации указано, что "этот метод вернет null, если этот компонент в настоящее время не отображается". Итак, когда я знаю, когда компонент готов к отображению, и у меня есть объект Graphics для изменения размера моего компонента?

Что такое запрос Swing invokation для рендеринга компонента после вызова фрейма setVisible (true)?

Спасибо


Обновление: вторник, фев 06, 2010 в 23:34

Как уже упоминалось в комментариях, GridLayout вообще не учитывает setXxxSize(). Для всех, кого это интересует, я опубликовал результаты использования GridLayout, BoxLayout и FlowLayout с использованием простого кадра, который получает 5 фиксированных размерных компонентов шириной 200 на 50 в высоту (путем установки минимального, максимального и предпочтительного).

Результаты тестирования:

GridLayout всегда изменяется по ширине и высоте (как указано в комментариях)

FlowLayout всегда уважал размер компонентов независимо.

Что касается BoxLayout...

PAGE_AXIS и Y_AXIS сокращают ширину компонентов примерно до половины их размера (104), но не уменьшают высоту.

LINE_AXIS и X_AXIS уменьшают высоту компонентов до нуля, но не касаются ширины.

Ответ 1

Сначала вы можете измерить свои строки, используя класс TextLayout и связанные с ним вещи. Например

public static void main(final String[] args) throws Exception
{
    final FontRenderContext frc = new FontRenderContext(null, true, true);
    final Font font = new Font("serif", Font.PLAIN, 18);
    final TextLayout layout = new TextLayout("This is a test", font, frc);
    final Rectangle2D bounds = layout.getBounds();
    System.err.println((int) (bounds.getWidth() + .5));
}

Во-вторых, вы можете узнать, когда ваш компонент стал видимым, используя ComponentListener, но это не обязательно для измерения ваших строк в "вперед"!

Ответ 2

Используйте JLabel для рендеринга ваших строк, тогда вы можете просто использовать метод getPreferredSize() метки l.