2

我试图了解 getListCellRendererComponent 方法的工作原理,但我不明白。我创建了一个扩展 BasicComboBoxRenderer 的单独类,并添加了一个计数器,每次调用 getListCellRendererComponent 时都会打印该计数器。然后,我使用 main 方法运行一个测试类,该方法显示一个只有一个 JComboBox 的框架,该 JComboBox 使用我的自定义渲染器类。这个组合框总共有 3 个项目,我设置了 setMaximumRowCount(2) 所以它只显示其中 2 个。

  • 当我第一次运行程序并出现带有组合框的框架时,计数器通知 getListCellRendererComponent 被调用了 6 次。
  • 当框架失去焦点时(例如,当我单击桌面时)该方法执行 1 次。
  • 当框架重新获得焦点(单击我的框架)时,该方法执行 1 次。
  • 当我单击箭头按钮并第一次出现下拉列表时,计数器说该方法执行了 8 次。
  • 当我再次单击箭头按钮并且列表消失时,该方法被调用 1 次(这种情况总是发生)。
  • 当我在第一次之后单击箭头按钮时,该方法被调用了 5 次。
  • 当我单击滚动条按钮向上或向下时,该方法执行 1 次。
  • 当我将光标移动到列表中未选中的项目上时,该方法执行 2 次,然后再执行 1 次(这是最荒谬的)
  • 当我单击列表中的一个项目时,该方法执行 4 次。

一开始我以为这个方法的执行次数与列表中项目的数量一样多(再加上出现在组合框显示区域上的次数)。

但是从上面我只能理解一两种情况,比如当我点击滚动条按钮,方法执行1次时,可能是因为渲染了一个新项目。其他人看起来都疯了……

4

2 回答 2

2

我希望在任何时候都会调用渲染器的不少于 n + 1 次迭代。

该组件需要

  1. 找出内容的最佳尺寸。这可以通过使用原型值来实现,或者,如果未指定,则遍历所有项目以找到最大边界(即 3 次)
  2. 如果存在+1次,则渲染所选项目
  3. 如果弹出窗口可见 +3 次,则渲染列表
  4. 可能寻找工具提示

= 可能的 7 次迭代

失去焦点时,组件需要渲染选中项+1

重新获得焦点时,组件将再次尝试渲染所选项目+1

显示弹出窗口时,请参阅第一部分

第二次可能表明组件已经缓存了第一个弹出操作的结果(可能是组件在焦点事件之间使其内部缓存失效)

每次更改滚动窗格的视图时,它都需要渲染以前未在屏幕上显示的任何项目,这是出于优化的原因(想象一个有 100 个项目的 lst,渲染所有项目是浪费时间,因此包含原型值)

鼠标动作可以触发一系列不同的动作,鼠标移入、鼠标移出、鼠标移动。最有可能这些与工具提示管理器和组件有关,试图确定工具提示是否可用

尝试设置原型值并查看组件显示其弹出窗口时是否会更改迭代次数

于 2012-07-11T20:36:43.510 回答
1
  1. 我认为您忘记描述在,Object(s)中创建或重新创建的方式和方式Renderer

  2. 您忘记将您RendererSSCCE表格中的看法发送到这里

  3. 那么一切都在学术水平上,很难写一些关于你的Renderer...

  4. Renderer对每一个事件Mouse做出反应Key

  5. Renderer从所有重要方法的输出到System.out.println("yyyy")

.

import java.awt.Component;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.plaf.basic.BasicComboBoxRenderer;

public class ComboBoxHoverOver {

    private JComboBox combo = new JComboBox();

    public ComboBoxHoverOver() {
        combo.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXX");
        combo.setRenderer(new ComboToolTipRenderer(combo));
        combo.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                System.out.println("itemStateChanged");
            }
        });
        combo.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("actionPerformed");
            }
        });
        combo.addItem("");
        combo.addItem("Long text 4");
        combo.addItem("Long text 3");
        combo.addItem("Long text 2");
        combo.addItem("Long text 1");
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(combo);
        f.pack();
        f.setVisible(true);
    }

    private class ComboToolTipRenderer extends BasicComboBoxRenderer {

        private static final long serialVersionUID = 1L;
        private JComboBox combo;
        private JList comboList;

        ComboToolTipRenderer(JComboBox combo) {
            this.combo = combo;
        }

        @Override
        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
            super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            System.out.println(value + ", " + index + ", " + isSelected + ", " + cellHasFocus);
            if (comboList == null) {
                comboList = list;
                KeyAdapter listener = new KeyAdapter() {

                    @Override
                    public void keyReleased(KeyEvent e) {
                        if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_UP) {
                            int x = 5;
                            int y = comboList.indexToLocation(comboList.getSelectedIndex()).y;
                            System.out.println("keyReleased " + comboList.getSelectedIndex());
                        }
                    }
                };
                combo.addKeyListener(listener);
                combo.getEditor().getEditorComponent().addKeyListener(listener);
                comboList.addListSelectionListener(new ListSelectionListener() {

                    public void valueChanged(ListSelectionEvent e) {
                        if (e.getValueIsAdjusting()) {
                            JList list = (JList) e.getSource();
                            int item = list.getSelectedIndex();
                            if (item > -1) {
                                String string = list.getSelectedValue().toString();
                                System.out.println("valueChanged " + list.getSelectedValue().toString());
                            }
                        }
                    }
                });
            }
            if (isSelected) {
                System.out.println("isSelected " + value.toString());
            }
            return this;
        }
    }

    public static void main(String[] args) {

        java.awt.EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                ComboBoxHoverOver comboBoxHoverOver = new ComboBoxHoverOver();
            }
        });
    }
}
于 2012-07-11T21:10:40.747 回答