【问题标题】:Java Generics: how to solve warning on call to JComboBox.setRendererJava 泛型:如何解决对 JComboBox.setRenderer 的调用警告
【发布时间】:2020-11-18 07:43:29
【问题描述】:

在多年中断后回到 Java,并在中途向内部库添加一些代码。有问题的类是 JComboBox 的扩展,它确保禁用的项目显示为灰色且不可选择。部分代码基于https://www.algosome.com/articles/enable-disable-jcombobox.html 中的代码。这个想法是我们有 (1) 一个数据模型,它确保只能选择启用的项目,以及 (2) 一个自定义渲染器,它显示禁用的项目灰色:

代码可以运行,但编译器对我的泛型并不完全满意。我真的更希望有一个快乐的编译器,但我不知道在这种情况下如何实现这一点。下面是一个 SSCCE,它产生了上面的组合框。我为篇幅道歉;这真的是我能得到的最短的。外部类包含几个内部类;所有将存在于库中的类都在其名称前加上LibMyComboBox 只是为了演示代码。

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

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

【问题讨论】:

    标签: java generics compiler-warnings


    【解决方案1】:

    主要问题在BasicComboBoxRenderer内部,因为该类没有ListCellRenderer接口的泛型参数,但JComboBox类需要泛化aRenderer变量,参见sn-p:

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

    作为解决方法,我可以建议将所有逻辑从 BasicComboBoxRenderer 复制到您自己的自定义类中,并为 ListCellRenderer 添加泛型类型,并且该 approcu 将解决编译过程中的警告。

    【讨论】:

      猜你喜欢
      • 2020-02-04
      • 1970-01-01
      • 1970-01-01
      • 2016-04-20
      • 2011-02-25
      • 2013-03-08
      • 2013-04-29
      • 1970-01-01
      • 2021-03-27
      相关资源
      最近更新 更多