java泛型:如何解决调用jcombobox.setrenderer时的警告

ohtdti5x  于 2021-07-11  发布在  Java
关注(0)|答案(1)|浏览(285)

在中断多年后回到java,并在向内部库添加一些代码的过程中完成了一半。所讨论的类是jcombobox的扩展,它确保禁用的项变灰并且不可选择。有些代码是基于https://www.algosome.com/articles/enable-disable-jcombobox.html. 我们的想法是:(1)有一个数据模型,确保只能选择已启用的项;(2)有一个自定义呈现器,将已禁用的项显示为灰色:


代码正在运行,但是编译器对我的泛型不太满意。我真的希望有一个快乐的编译器,但我不知道如何在这种情况下实现这一点。下面是一个sscce,它生成上面的组合框。很抱歉这么长时间;这真是我能买到的最短的了。外部类包含几个内部类;图书馆里所有的班级都有 Lib 在他们的名字前面; MyComboBox 只是为了演示代码。

import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

public class SSCCE extends JPanel
{
    //--------------------LIB CB ITEM--------------------------------------------------
    private class LibCBItem extends JMenuItem
    {
        private LibCB myComboBox;

        LibCBItem(String title, LibCB parent)
        {
            super(title);
            myComboBox = parent;
        }

        public void setEnabled(boolean b)
        {
            boolean changeSelection = false;

            if (!b && isEnabled() && this.equals(myComboBox.getSelectedItem())) {
                int enabledCount = myComboBox.getEnabledItemCount();
                if (enabledCount == 2)
                    changeSelection = true;
                else if (enabledCount == 1)
                    System.out.println("setEnabled(FALSE) on final remaining enabled item");
                else
                    System.out.println("setEnabled(FALSE) of selected item with " + enabledCount + " enabled items: must change selection before disabling");
            }

            super.setEnabled(b);

            if (changeSelection)
                myComboBox.selectEnabledItem();
        }

        public String toString()
        {
            return getText();
        }
    }

    //--------------------LIB CB DATA MODEL--------------------------------------------------
    private class LibCBDataModel<T extends LibCBItem> extends DefaultComboBoxModel<T>
    {
        public void setSelectedItem(Object o)
        {
            LibCBItem item = (LibCBItem) o;
            if (item != null) {
                if (item.isEnabled())
                    super.setSelectedItem(item);
            }
            else {
                super.setSelectedItem(null);
            }
        }
    }

    //--------------------LIB CB RENDERER--------------------------------------------------
    private class LibCBRenderer extends BasicComboBoxRenderer
    {
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
        {
            JLabel c = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            LibCBItem item = (LibCBItem) value;
            if (item.isEnabled()) {
                c.setBackground(super.getBackground());
                c.setForeground(super.getForeground());
                if (isSelected) // is the mouse over it?
                    c.setText("√ " + c.getText());
                else
                    c.setText("    " + c.getText());
            }
            else {
                if (isSelected) // is the mouse over it?
                    c.setBackground(UIManager.getColor("ComboBox.background"));
                else
                    c.setBackground(super.getBackground());

                c.setForeground(Color.lightGray);

                c.setText("    " + c.getText());
            }
            return c;
        }
    }

    //--------------------LIB CB--------------------------------------------------
    private class LibCB<T extends LibCBItem> extends JComboBox<T>
    {
        LibCB()
        {
            super();
            setModel(new LibCBDataModel<>());
            setRenderer(new LibCBRenderer());
            //Warning:(127, 36) java: unchecked method invocation: method setRenderer in class javax.swing.JComboBox is applied to given types
            //  required:
            //    javax.swing.ListCellRenderer<? super E>
            //  found:
            //    SSCCE.LibCBRenderer
            //Warning:(127, 37) java: unchecked conversion
            //  required:
            //    javax.swing.ListCellRenderer<? super E>
            //  found:
            //    SSCCE.LibCBRenderer
        }

        int getEnabledItemCount()
        {
            int returnVal = 0;
            for (int i = 0; i < getItemCount(); i++) {
                if (getItemAt(i).isEnabled())
                    returnVal++;
            }
            return returnVal;
        }

        void selectEnabledItem()
        {
            boolean selectedOne = false;
            for (int i = 0; i < getItemCount(); i++) {
                if (getItemAt(i).isEnabled()) {
                    setSelectedIndex(i);
                    selectedOne = true;
                    break;
                }
            }
            if (!selectedOne)
                System.out.println("selectEnabledItem() with 0 enabled items in combo box");
        }
    }

    //--------------------MY COMBO BOX--------------------------------------------------
    private class MyComboBox extends LibCB<LibCBItem>
    {
        MyComboBox()
        {
            LibCBItem item1 = new LibCBItem("1st", this);
            addItem(item1);
            LibCBItem item2 = new LibCBItem("2nd", this);
            addItem(item2);
            LibCBItem item3 = new LibCBItem("3rd", this);
            addItem(item3);

            item2.setEnabled(false);
        }
    }

    //--------------------SSCCE--------------------------------------------------
    SSCCE()
    {
        JFrame frame = new JFrame("SSCCE");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setOpaque(true);
        frame.setContentPane(this);
        frame.add(new MyComboBox());
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args)
    {
        javax.swing.SwingUtilities.invokeLater(() -> new SSCCE());
    }
}

编译器在同一行上给了我两个警告 LibCB() 它叫什么 JComboBox.setRenderer() . 我已将警告的文本粘贴到内联。为了便于参考:

Warning:(127, 36) java: unchecked method invocation: method setRenderer in class javax.swing.JComboBox is applied to given types
  required:
    javax.swing.ListCellRenderer<? super E>
  found:
    SSCCE.LibCBRenderer
Warning:(127, 37) java: unchecked conversion
  required:
    javax.swing.ListCellRenderer<? super E>
  found:
    SSCCE.LibCBRenderer

有没有人能给我指出解决这些问题的方向,让编译器满意?Java8,以防万一。非常感谢!

yqyhoc1h

yqyhoc1h1#

主要问题是 BasicComboBoxRenderer ,因为该类没有 ListCellRenderer 接口,但是 JComboBox 类期望广义 aRenderer 变量,请参见代码段:

public void setRenderer(ListCellRenderer<? super E> aRenderer) {
        ListCellRenderer<? super E> oldRenderer = renderer;
        renderer = aRenderer;
        firePropertyChange( "renderer", oldRenderer, renderer );
        invalidate();
    }

作为解决方法,我可以建议从 BasicComboBoxRenderer 您自己的自定义类,并为添加泛型类型 ListCellRenderer ,该方法将解决编译过程中的警告问题。

相关问题