JTextField を含むいくつかの子要素を持つカスタム Swing コンポーネントがあります。コンテナに JTextField と同じベースラインを設定したいので、コンテナの getBaseline メソッドをオーバーライドしました。ただし、コンテナーに対して getBaseline が呼び出されたときに、JTextField の位置が常に設定されるとは限りません。コンテナーの getBaseline メソッドに doLayout への呼び出しを追加しようとしましたが、役に立ちませんでした。私が欲しいのは次のとおりです。
public int getBaseline(int w, int h) {
Dimension size = textField.getPreferredSize();
int textBaseline = textField.getBaseline(size.width, size.height);
int textY = textField.getY();
return textY + textBaseline;
}
上記のコードでは、textY は 0 です。
問題を説明するためにいくつかのコードを書きました。初めて「追加」をクリックすると、ベースラインが間違っています。2回目は正解です。
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
class CustomComponent extends JPanel {
public CustomComponent() {
setLayout(new GridBagLayout());
textField.setColumns(8);
layoutElements();
}
public void addComponent() {
JPanel comp = new JPanel();
comp.setPreferredSize(new Dimension(50, 200));
comp.setBackground(Color.red);
otherComponents.add(comp);
layoutElements();
}
public int getBaseline(int w, int h) {
Dimension size = textField.getPreferredSize();
return textField.getY() + textField.getBaseline(size.width, size.height);
}
public Component.BaselineResizeBehavior getBaselineResizeBehavior() {
return Component.BaselineResizeBehavior.CONSTANT_DESCENT;
}
private void layoutElements() {
removeAll();
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.SOUTH;
add(textField, constraints);
for (JPanel comp : otherComponents)
add(comp, new GridBagConstraints());
if (getParent() != null)
getParent().validate();
}
private JTextField textField = new JTextField();
private ArrayList<JPanel> otherComponents = new ArrayList<JPanel>();
}
public class Main {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
panel.setLayout(new GridBagLayout());
frame.getContentPane().add(panel);
JButton addComponent = new JButton("Add");
GridBagConstraints constraints = new GridBagConstraints();
constraints.anchor = GridBagConstraints.BASELINE;
panel.add(addComponent, constraints);
final CustomComponent customComp = new CustomComponent();
panel.add(customComp, constraints);
addComponent.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
customComp.addComponent();
}
});
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}