【问题标题】:Why is Swing taking such a long time to create this panel?为什么 Swing 需要这么长时间来创建这个面板?
【发布时间】:2016-04-30 16:09:28
【问题描述】:

我目前正在编写程序的一部分,将动态数量的 JComboBoxes 插入 JPanel,但是我注意到它非常慢(大约需要 10 秒才能完成),并且它会将整个 Swing 线程冻结到做。我不确定有什么更好的解决方案,但我知道有更好的方法。

private JPanel createInventoryPanel(PlayerInventory inventory)
{
    JPanel panel = new JPanel();
    panel.setLayout(new MigLayout("debug"));

    int columns = 4;
    int rows = inventory.getSize() / 4;
    int index = 0;
    for (int i = 0; i < columns; i++)
    {
        for (int j = 0; j < rows; j++)
        {
            GameItem item = inventory.getItems().get(index);

            JComboBox box = new JComboBox(itemNames);
            box.setEditable(true);
            AutoCompleteDecorator.decorate(box);
            box.setSelectedItem(WordUtils.capitalizeFully(item.getName()) + " (0x" + HexUtil.shortToHexString(item.getValue()) + ")");

            boolean shouldWrap = ((index + 1) % 4 == 0) && index != 0;

            panel.add(box, "" + (shouldWrap ? "wrap" : ""));
            itemBoxes.add(box);

            index++;
        }
    }

    return panel;
}

所以解释一下我的代码:

我有一个 JFrame 和一个 JTabbed 窗格。在选项卡式窗格中,我正在创建这个“库存面板”以适应它。在库存面板中,有一个 JComboBoxes 的“网格”(行和列),其中数量是库存的大小。每个组合框都是可自动完成的(在键入时)以便于使用。

所以我创建了 Jpanel,将其设置为 MigLayout(使用调试进行可视化调试)。

有 4 列(我选择了这个数字) 行数取决于库存大小除以 4 列。简单的东西。

当然,我在 for 循环中使用 for 循环来创建我的 jcomboboxes XY 网格。这是它变得非常缓慢的地方。我不确定循环是否很慢(我怀疑,因为它是简单的算术)或者是否存在线程问题或什么..

WordUtils 是 Apache 的 Commons-Lang 库的一部分,AutoCompleteDecorator 用于 JComboBoxes 通过 SwingX 库自动完成。

GameItem 只是一个表示游戏项目的对象,其中包含一些小值(短裤、字节等。与此无关)。

我不知道如何让它更快。

【问题讨论】:

  • 任何分析器都会告诉您比我们的假设更多的信息
  • This answer on SO 可能是您的问题。它与 JTabbedPane 和 MigLayout 一起使用。
  • @AdamSkywalker 问题是渲染了这么多摇摆物体,速度很慢......但我不知道另一种方法。
  • @lschuetze 我看到了,不幸的是它没有解决我的问题。

标签: java swing autocomplete swingx


【解决方案1】:

不要使用自动完成装饰器。改用这个Example: Adding Autocomplete to JTextField

【讨论】:

    【解决方案2】:

    所以我发现问题并不是特别是渲染问题,而是 JComboBox 对超过一定数量的条目大小造成了荒谬的影响。我在 50 多个盒子中输入了大约 4,700 件商品,所以它的性能确实受到了影响。

    不幸的是,尽管我很想使用 JComboBox ,但我将切换到 JTextField ..

    【讨论】:

    • 然后this 将使您能够一次添加所有项目。
    【解决方案3】:

    速度非常慢(大约需要 10 秒才能完成)

    首先测量执行时间。测量执行时间的一种简单方法是使用System.nanoTime()。将您的代码更改为以下内容:

     long start = System.nanoTime();
     try {
        // The code you want to measure
     } finally {
          long end = System.nanoTime();
          long execTime = end - start;
          System.out.println("Execution of .... took " + execTime + "ns";
     }
    

    ...或者您使用分析器。您可以使用jvisualvm's profilerjvisualvm 通常位于JDK_HOME/bin

    【讨论】:

    • 我知道什么需要最长时间,但我不知道如何让它更快.. 分析只会告诉我它很慢。我可以看到问题在于绘制了这么多组件,但我没有解决方法。
    【解决方案4】:

    我认为这是因为你同时创造了太多东西。而且我认为JComboBox 是一个渲染起来非常复杂的东西。

    但是,这不能在另一个线程上完成,因为您正在创建 UI 组件,这必须在 UI 线程(主线程)上完成。

    我也遇到过这种情况。但那是我创建 Windows 窗体应用程序的时候,这是一种完全不同的技术。但我认为基本思想是一样的。

    我想将 100 个 UI 组件添加到 Panel(类似于 JPanel)。而且花了很长时间。所以我决定在顶部显示另一个Panel 以覆盖Panel(我正在添加内容的那个)。然后我在封面板上贴了一个标签,上面写着“正在加载”。这样,人们就会知道它正在加载并且不会惊慌失措。当然,生成组件后我隐藏了覆盖面板

    令人惊讶的是,当我运行程序时,封面面板只出现了片刻!消失后,我看到我想生成的东西都已经生成了!

    所以我得出一个结论,UI组件如果不需要渲染,会显得更快。

    您可能应该这样做。在生成组合框时,将JPanel 放在另一个上面。完成后,再次隐藏面板,或将其完全移除。

    【讨论】:

    • 使用CardLayout 更改视图。
    猜你喜欢
    • 2016-05-29
    • 2011-10-07
    • 2011-08-27
    • 2011-12-07
    • 1970-01-01
    • 2012-08-09
    • 2021-07-26
    • 1970-01-01
    相关资源
    最近更新 更多