2012-07-11 38 views
0

我想了解getListCellRendererComponent方法如何工作,但我不明白。我做了一个扩展BasicComboBoxRenderer的单独的类,并且每次调用getListCellRendererComponent时都添加一个计数器。然后,我使用一个主要方法运行一个测试类,该方法只显示一个使用我的自定义渲染器类的JComboBox。这个组合框总共有3个项目,我设置了setMaximumRowCount(2),所以它只显示其中的2个。getListCellRendererComponent被调用了多少次?

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

起初我以为这个方法会被执行的次数与列表中的项数一样多(再加上一个出现在组合框显示区上的项)。

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

+0

请发表相关代码。 – 2012-07-11 20:01:24

+0

我相信每次JComboBox中的任何一行需要重新绘制时都会调用它。发生的次数是不可预测的,部分取决于LAF。你不需要知道它被调用的频率。您只需确保该方法可以快速运行。 – Enwired 2012-07-11 20:39:07

+1

如果你真的想知道,只需在该方法中放置一个断点,或转储当前的堆栈跟踪。你会立即看到它被叫的地方,很可能是为什么叫它。 – Robin 2012-07-11 21:45:50

回答

1

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

的组件需要

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

=可能的7次迭代

当失去焦点,该组件需要呈现所选择的项目1

当重新获得焦点,该组件将尝试渲染TE选择的项目再次+1

当显示弹出窗口,看到的第一部分

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

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

鼠标操作可以触发一系列不同的操作,鼠标移入,鼠标移出,鼠标移动。大多数likly这些都与工具提示经理和组件试图确定是否提示可用做

尝试设置一个原型值&看看是否改变迭代次数,当组件显示其弹出

+0

设置原型值时确实存在差异..不是当弹出窗口显示时,而是第一次加载组合框时。计数器说4倍而不是6 ..这使我更困惑.. – Rempelos 2012-07-12 15:28:42

+0

好吧,回到Java 1.3,当Swing第一次被引入核心API时,组合框将呈现列表中的所有项目。这意味着如果你有100个项目,在用户点击和弹出窗口之间可能需要几秒钟的时间(记住,这是10年前,我们有1ghz机器,其中1g的RAM被认为是过度的)。所以在1.4(我认为)他们引入了原型值的概念 - 它允许组合框能够“猜测”组件的大小,而不需要遍历项目列表并渲染所有项目。 – MadProgrammer 2012-07-12 22:50:04

1
  1. 我认为你忘了描述你如何和Object(s)创建或Renderer re_create,

  2. 你忘了这里发送您的视图有关RendererSSCCE形式

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

  4. Renderer反应到每个MouseKey事件

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