これが私がこれまでに得たものですが、1つの大きな問題はクロスL&Fの問題です。別の方法は、ComboBoxモデルのすべての値と「選択なし」の値を調べて、どれが最も長いかを確認することです。次に、それをprototypeDisplayValueとして設定できます。問題は、各文字列の境界を測定するためのグラフィカルコンテキストが必要なことです。
@Enwiredと@Robinで見つけた2つのソリューションを次に示します。両方に感謝します。
編集:@Robinと話し合った後、このソリューションは実際にははるかに単純であり、すべてのプラットフォームとルックアンドフィールで機能することがわかりました。唯一の欠点は、追加のJComboBoxを作成する必要があることです。
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UnsupportedLookAndFeelException;
public class TestComboBox {
protected void initUI() {
JFrame frame = new JFrame(TestComboBox.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridBagLayout());
JComboBox comboBox = new JComboBox(new Object[] { "Something", "Stuff", "Beep" }) {
private JComboBox internal;
private JComboBox getInternalComboBox() {
if (internal == null) {
internal = new JComboBox(new Object[] { null });
}
return internal;
}
@Override
public Dimension getPreferredSize() {
Dimension preferredSize = super.getPreferredSize();
if (getSelectedItem() == null) {
getInternalComboBox().setRenderer(getRenderer());
Dimension nullDimension = getInternalComboBox().getPreferredSize();
preferredSize.width = Math.max(preferredSize.width, nullDimension.width);
preferredSize.height = Math.max(preferredSize.height, nullDimension.height);
}
return preferredSize;
}
@Override
public void updateUI() {
internal = null;
super.updateUI();
}
};
comboBox.setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value == null) {
setText("No selection");
}
return comp;
}
});
comboBox.setSelectedItem(null);
panel.add(comboBox);
frame.add(panel);
frame.setSize(200, 100);
frame.setVisible(true);
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TestComboBox().initUI();
}
});
}
}
編集2:@Enwiredと話し合った後、ListCellRenderergetPreferredSizeを直接オーバーライドするこの代替ソリューションが思い浮かびました。これでは、利用可能なさまざまなL&Fを試すことができます。
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;
public class TestComboBox {
protected void initUI() {
final JFrame frame = new JFrame(TestComboBox.class.getSimpleName());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new JPanel(new GridBagLayout());
JComboBox comboBox = new JComboBox(new Object[] { "Something", "Stuff", "Beep" });
comboBox.setRenderer(new DefaultListCellRenderer() {
private Dimension nullDimesion;
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value != null && nullDimesion == null) {
nullDimesion = ((JComponent) getListCellRendererComponent(list, null, -1, false, false)).getPreferredSize();
}
Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value == null) {
setText("No selection");
}
return comp;
}
@Override
public Dimension getPreferredSize() {
Dimension preferredSize = super.getPreferredSize();
if (nullDimesion != null) {
preferredSize.width = Math.max(preferredSize.width, nullDimesion.width);
preferredSize.height = Math.max(preferredSize.height, nullDimesion.height);
}
return preferredSize;
}
@Override
public void updateUI() {
nullDimesion = null;
super.updateUI();
}
});
comboBox.setSelectedItem(null);
final JComboBox uiComboBox = new JComboBox(UIManager.getInstalledLookAndFeels());
uiComboBox.setRenderer(new DefaultListCellRenderer() {
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
Component comp = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof LookAndFeelInfo) {
LookAndFeelInfo info = (LookAndFeelInfo) value;
setText(info.getName());
}
return comp;
}
});
uiComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(((LookAndFeelInfo) uiComboBox.getSelectedItem()).getClassName());
SwingUtilities.updateComponentTreeUI(frame);
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (InstantiationException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IllegalAccessException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (UnsupportedLookAndFeelException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
}
});
panel.add(comboBox);
panel.add(uiComboBox);
frame.add(panel);
frame.setSize(300, 100);
frame.setVisible(true);
}
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException,
UnsupportedLookAndFeelException {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new TestComboBox().initUI();
}
});
}
}