是否可以快速替换JComboBox/BasicComboBoxUI? [英] Fast replacement for JComboBox / BasicComboBoxUI?

查看:88
本文介绍了是否可以快速替换JComboBox/BasicComboBoxUI?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个JComboBox,它可能具有数千个项目.它们经过排序,并且可以按需输入,因此从原则上讲,它并不是完全不可用的.

I've got a JComboBox that potentially can have thousands of items. They're sorted, and there's find-as-you-type, so in principle it's not completely unusable.

在实践中,仅使用几百个项目就无法使用.我设法使用setPrototypeDisplayValue()改善了初始显示性能,但是BasicListUI仍然坚持为框中的每个项目配置列表单元格渲染器(请参见BasicListUI.updateLayoutState()).

In practice, it's pretty unusable with just a couple of hundred items. I managed to improve the initial display performance using setPrototypeDisplayValue(), but BasicListUI still insists on configuring the list cell renderer for every item in the box (see BasicListUI.updateLayoutState()).

这个或类似的东西显然是一个已知问题到太阳;已经过去八年了,所以我没有屏住呼吸.

This, or something like it, is apparently a known issue to Sun; it has been for going on eight years now, so I'm not holding my breath.

实现我自己的UI的捷径,有人解决过吗?

Short of implementing my own UI, has anyone got a workaround?

推荐答案

这是我想到的技巧.缺点是:

Here's the hack that I came up with. The drawbacks are:

  • 如果要保持外观,则必须分别关注每个BasicComboBoxUI扩展名的子类
  • 您必须使用反射来加载UI类,因为(例如)WindowsComboBoxUI的子类在Linux上不会加载
  • 它不能与不扩展BasicComboBoxUI
  • 的L& F(例如MacOS?)一起使用
  • 它对ListCellRenderer做出的假设可能并不总是必要的
  • if you want to maintain the look and feel, you have to separately subclass each BasicComboBoxUI extension you care about
  • you have to use reflection to load your UI classes, since (for instance) a subclass of WindowsComboBoxUI won't load on Linux
  • it won't work with L&Fs (e.g. MacOS?) that don't extend BasicComboBoxUI
  • it makes assumptions about the ListCellRenderer that may not always be warranted

我仍然对清洁的解决方案持开放态度.

I'm still open to cleaner solutions.

class FastBasicComboBoxUI extends BasicComboBoxUI {
  @Override
  public void installUI(JComponent c) {
    super.installUI(c);

    Object prototypeValue = this.comboBox.getPrototypeDisplayValue();
    if (prototypeValue != null) {
      ListCellRenderer renderer = comboBox.getRenderer();
      Component rendererComponent = renderer
          .getListCellRendererComponent(this.listBox, 
              prototypeValue, 0, false, false);
      if (rendererComponent instanceof JLabel) {
        // Preferred size of the renderer itself is (-1,-1) at this point, 
        // so we need this hack
        Dimension prototypeSize = new JLabel(((JLabel) rendererComponent)
            .getText()).getPreferredSize();
        this.listBox.setFixedCellHeight(prototypeSize.height);
        this.listBox.setFixedCellWidth(prototypeSize.width);
      }
    }
  }
}

我仍然对清洁的解决方案持开放态度.

I'm still open to cleaner solutions.

稍后

结果证明这只能解决部分问题.带有大量项目的组合框的初始显示可能仍然很慢.我必须通过将代码移到ComboPopup本身中来确保弹出列表框立即获得固定的单元格大小,如下所示.请注意,如上所述,这取决于原型值.

Turns out this only solved some of the problems. Initial display of a combo box with a large number of items could still be really slow. I had to make sure the popup list box immediately gets a fixed cell size, by moving the code into the ComboPopup itself, as follows. Note that, as above, this depends on the prototype value.

@Override
protected ComboPopup createPopup() {
  return new BasicComboPopup(comboBox) {
    @Override
    protected JList createList() {
      JList list = super.createList();
      Object prototypeValue = comboBox.getPrototypeDisplayValue();
      if (prototypeValue != null) {
        ListCellRenderer renderer = comboBox.getRenderer();
        Component rendererComponent = renderer
            .getListCellRendererComponent(list, prototypeValue, 0, false, false);
        if (rendererComponent instanceof JLabel) {
          // Preferred size of the renderer itself is (-1,-1) at this point, 
          // so we need this hack
          Dimension prototypeSize = new JLabel(((JLabel) rendererComponent)
              .getText()).getPreferredSize();
          list.setFixedCellHeight(prototypeSize.height);
          list.setFixedCellWidth(prototypeSize.width);
        }
      }
      return list;
    }
  };
}

这篇关于是否可以快速替换JComboBox/BasicComboBoxUI?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆