2

ローカル システムのルック アンド フィールを使用する Java アプリケーションを作成しています。プログラムには、色付きのドット (カスタム JComponment) とそれに続くオブジェクトを指定したテキストをレンダリングする ListCellRenderer があります。これは、Swing のデフォルトの Metal ルック アンド フィールを使用する場合にうまく機能します。

ただし、Windows のルック アンド フィールを使用すると、セルはドロップダウン リストで正しくレンダリングされますが、選択されたアイテム (ユーザーが別のオプションを選択していないときに表示されるアイテム) はテキストのみをレンダリングし、色付きのドットを無視します。レンダラーを変更してフォントを設定すると、ドロップダウンと選択した項目の両方で適切なフォントが表示されるため、セル レンダラーが少なくとも部分的に使用されていることがわかります。

このような問題を引き起こしているさまざまな LAF に関する Web 上の投稿をいくつか読みましたが、私の特定の問題について話し合っている人に出会ったことはありません。

興味のある方のために、コードは次のとおりです。

.

@Override
public Component getListCellRendererComponent(JList<? extends ColoredDisplayable> jlist, ColoredDisplayable e, int i, boolean isSelected, boolean hasFocus) {

    JPanel cell = new JPanel(new GridBagLayout());
    cell.setOpaque(false);

    JLabel label = new JLabel(e.getDisplayString());
    label.setOpaque(false);
    label.setBorder(BorderFactory.createEmptyBorder(1, 4, 1, 4));
    label.setHorizontalAlignment(JLabel.LEFT);

    Color deselectedBackground = cell.getBackground();
    Color deselectedTextColor = cell.getForeground();

    // LAYOUT COMPONENTS
    // Dot
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 0;
    gbc.gridy = 0;
    gbc.insets = INSETS;
    gbc.anchor = GridBagConstraints.LINE_START;
    gbc.weightx = 0.0f;
    gbc.fill = GridBagConstraints.NONE;
    cell.add(new Dot(e.getColor()), gbc);

    // Label
    gbc.gridx = 1;
    gbc.weightx = 1.0f;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    cell.add(label, gbc);


    if (isSelected){
        cell.setOpaque(true);
        cell.setBackground(MetalLookAndFeel.getTextHighlightColor());
    } else {
        cell.setBackground(deselectedBackground);
        cell.setForeground(deselectedTextColor);
    }

    return cell;
}

また、カスタム コンポーネントのコードは次のとおりです。誰かがこれを試して、私がここでばかげたことをしているだけかどうかを確認してください。

public class Dot extends JComponent {

    /** The size of the dot. */
    private static final int SIZE = 10;

    /** The size of the dot. */
    private static final int PAD = 4;

    private static final Dimension DIM = new Dimension(SIZE + PAD, SIZE + PAD);

    /** The Color to render the dot. */
    private final Color m_color;

    /** The Dot itself. */
    private static final Ellipse2D.Double DOT = new Ellipse2D.Double(PAD / 2, PAD / 2, SIZE, SIZE);

    /**
     * Creates a dot of the specified color.
     * @param color the color to make the dot.
     */
    public Dot(Color color) {
        m_color = color;
    }

    @Override
    public void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setColor(m_color);
        g2d.fill(DOT);
    }

    @Override
    public Dimension getPreferredSize() {
        return DIM;
    }
}

編集: これをUbuntu 12.04でテストしたところ、セルレンダラーは期待どおりに機能しました(ただし、カスタムレンダラーが適用されていない場合のように、JComboboxは外側の境界線をレンダリングしませんでした)。

編集:これをさらに詳しく調べると、JComboBox の setEditor メソッドに何かがあるように見えますが、編集できない場合は、メソッドの状態の javadoc としてレンダラーを使用する必要があります。

JComboBox フィールドで選択された項目を描画および編集するために使用されるエディターを設定します。エディターは、受信側の JComboBox が編集可能な場合にのみ使用されます。編集できない場合、コンボ ボックスはレンダラーを使用して、選択した項目を描画します。

それは私が見ている動作ではないようです。Windows LAF のユーザーがセル レンダラーのすべての部分を監視できるようにするには、どうすればよいですか?

4

1 に答える 1

3

これを詳しく調べたところ、Windows LAF の場合、選択したセルを適切にレンダリングするには、ComboBoxEditor を設定し、JComboBox を編集可能に設定する必要があることがわかりました。

これは、JComboBox の setEditor メソッドの API が、編集できない場合はレンダラーが使用されることを示しているため、Windows ルック アンド フィールに固有のバグ/意図しない機能であると思われます。これは、デフォルトの Metal LAF と Ubuntu の両方で実行される場合です。 .

それに加えて、ListCellRenderer で行うように、getEditorComponent が呼び出されるたびにエディターに新しいセルを返すようにすることはできませんでした。これは理にかなっていると思います。

この Web サイトでは、エディターの作成方法の例を (つまらないものではありますが) 提供しています。

JComboBox と BasicComboBox の API も役に立ちました。

そして最後に、私のエディター コード:

public class ColoredDisplayableComboBoxEditor extends BasicComboBoxEditor {

    private ColoredDisplayable m_cd = null;
    private static final Insets INSETS = new Insets(3, 1, 3, 1);
    private final JPanel m_cell;
    private final JLabel m_label;
    private final Dot m_dot;

    public ColoredDisplayableComboBoxEditor() {
        // INITIALIZE
        // Panel
        m_cell = new JPanel(new GridBagLayout());
        m_cell.setOpaque(false);

        // Label
        m_label = new JLabel();
        m_label.setOpaque(false);
        m_label.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 4));
        m_label.setHorizontalAlignment(JLabel.LEFT);

        // Dot
        m_dot = new Dot(Color.BLACK);

        // LAYOUT
        // Dot
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = INSETS;
        gbc.anchor = GridBagConstraints.LINE_START;
        gbc.weightx = 0.0f;
        gbc.fill = GridBagConstraints.NONE;
        m_cell.add(m_dot, gbc);

        // Label
        gbc.gridx = 1;
        gbc.weightx = 1.0f;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        m_cell.add(m_label, gbc);
    }

    @Override
    public Component getEditorComponent() {
        return m_cell;
    }

    @Override
    public Object getItem() {
        System.out.println("getting item.");
        return m_cd;
    }

    @Override
    public void setItem(Object item) {
        System.out.println("setting item.");
        if (item instanceof ColoredDisplayable) {
            ColoredDisplayable cd = (ColoredDisplayable)item;
            if (!cd.equals(m_cd)) {
                System.out.println("--item actually set.");
                m_cd = cd;
                m_label.setText(m_cd.getDisplayString());
                m_dot.setColor(m_cd.getColor());
            }            
        } else {
            throw new IllegalArgumentException("Parameter item must be a ColoredDisplayable.");
        }
    }
}
于 2015-06-14T06:00:03.250 に答える