调用getListCellRendererComponent多少次?

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

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

起初我认为这个方法将被执行的次数与列表中的项目数量相同(再加上combobox显示区域中显示的一个项目)。

但是我只能理解上面的一两种情况,例如当我单击滚动条按钮并且该方法执行一次时,可能是因为渲染了一个新项目。 其余的人似乎疯了……

我希望在任何时候都可以调用渲染器的n + 1次迭代。

该组件需要

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

=可能的7次迭代

失去焦点时,组件需要呈现所选项目+1

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

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

第二次可能表示组件已缓存第一个弹出操作的结果(组件可能使焦点事件之间的内部缓存无效)

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

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

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

  1. 我想你忘了描述你在Renderer创建或重新创建的Object(s)Object(s)

  2. 你忘了在SSCCE表格中发送你对Renderer的看法

  3. 那么一切都在学术水平,而且很难写出你的Renderer ……

  4. Renderer对每个MouseKey事件做出反应

  5. plain 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(); } }); } }