У меня часто возникает проблема, что метод или свойство Swing требует, чтобы объект был реализован. Например, чтобы нарисовать JPanel, мне может понадобиться знать, насколько высок определенный шрифт, но эта информация недоступна до тех пор, пока панель не будет реализована, поэтому до этого я получу нулевой указатель. Хуже того, не всегда ясно (по крайней мере для меня), какие методы требуют реализации объекта, а какие нет.
Очевидно, я могу сделать что-то глупое:
Кажется невероятным, что нужно сделать это. Есть ли более элегантный способ принудительного осуществления, чтобы я мог получить надежный доступ к метрикам шрифтов?
Типичный пример кода:
void draw( Point2D center ){
String sLabel = owner.getLabel();
NodeData.DATA_TYPE eType = owner.data_type;
int iSymbolWidth = 10;
// build text
if( sLabel == null ) sLabel = "";
Font font = new Font( "TimesRoman", Font.PLAIN, 12 );
text_node.setTextPaint( Color.DARK_GRAY );
text_node.setText( sLabel );
text_node.setFont( font );
Panel_Main panel = owner.application.getDisplayPanel();
java.awt.FontMetrics fm = panel.canvas.getGraphics().getFontMetrics(); // <--- ERROR HERE
int iText_AdvanceWidth = ( int ) ( fm.stringWidth( sLabel ) * 1.2 ) + LABEL_MARGIN * 2;
int iText_Height = fm.getHeight();
.... etc
Часть проблемы заключается в том, что объект, на котором я рисую, принадлежит Piccolo, библиотеке рисования графа, поэтому библиотеке принадлежит paintComponent, а не мне. При роспинге через исходный код Piccolo мне кажется, что мне нужно переопределить один из своих внутренних методов: paint (PPaintContext paintContext), который в основном должен быть эквивалентен переопределению paintComponent.
Как обсуждалось здесь, каждый компонент Swing имеет делегат UI, который вычисляет правильный предпочтительный размер для компонента, учитывая выбранный пользователем Look & Feel. В результате самым элегантным решением является позволить менеджеру компоновки использовать предпочтительный размер компонентов. Невыполнение этого часто приводит к его патологическому поведению. Как показано здесь и здесь, вы можете validate()
контейнер-контейнер, чтобы получить желаемую геометрию перед setVisible()
, но это означает, что может быть оправдан другой подход. В качестве конкретного примера этот пример BoxLayout
лучше сделать с помощью GroupLayout
, проиллюстрированный здесь и здесь.
Как правило, вам нужно только изучить FontMetrics
, чтобы рассчитать предпочтительный размер ваших собственных компонентов, как показано здесь.
TextLayout
, как здесь, так и здесь .
paintComponent()
. Этот метод будет когда-либо вызываться только для реализованных компонентов.