【问题标题】:How to arrange JComboBox item如何排列 JComboBox 项
【发布时间】:2020-05-29 21:45:28
【问题描述】:

我有一个包含 9 个图像项的 JComboBox。我怎样才能将它们排列成 3*3?

我希望我的物品像这样排列

我已经用谷歌搜索了几天,但我不知道这个问题的关键字是什么。任何建议表示赞赏。感谢您阅读我的问题。

编辑:

感谢大家的反馈。 我正在制作一个地图编辑器,我可以将地图元素放在一起。 The editor. 3*3排列石板路更直观。用户可以很容易地知道哪些元素相互匹配。

我不一定使用组合框。我也考虑过使用按钮,但我认为按钮会浪费很多空间。因为我以后会有更多的地图元素。

【问题讨论】:

  • 在组合框中?您希望能够单独选择它们吗?
  • 是的,我想单独选择它们。我只是想改变他们出现的方式。
  • JComboBox 的默认实现可能无法做到这一点 - 您将不得不创建一个全新的组件来模仿它或自定义外观委托 - 有点两种情况下的工作量
  • 我同意@MadProgrammer 如果我尝试这样做,我可能会在 JDialog 上绘制图像。
  • 如果您愿意分享它的目的是什么,它可能会鼓励其他解决方案。

标签: java swing user-interface jcombobox


【解决方案1】:

组合框的弹出窗口使用 JList 组件来显示项目。

您可以访问和更改 JList 的方向以包装项目:

Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
BasicComboPopup popup = (BasicComboPopup)child;
JList list = popup.getList(); 
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(3);

这将允许您使用向上/向下键浏览项目。

要支持使用左/右键导航,您需要在组合框中添加额外的Key Bindings

InputMap im = comboBox.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
im.put(KeyStroke.getKeyStroke("LEFT"), "selectPrevious");
im.put(KeyStroke.getKeyStroke("RIGHT"), "selectNext");

但是,弹出窗口基于添加到组合框中的最大项目的宽度。这将是一个问题,因为您不会看到所有项目。当您使用按键导航时,这些项目会滚动,但您不会同时看到所有 9 个项目。

要解决此问题,请查看Combo Box Popup。它具有允许您控制弹出窗口的大小/行为的功能。你会使用:

BoundsPopupMenuListener listener = new BoundsPopupMenuListener(true, false);
comboBox.addPopupMenuListener( listener );

【讨论】:

    【解决方案2】:

    可以通过为 JComboBox 提供自定义 UI 来做到这一点。但是,至少在我的情况下,该 UI 是一团糟,因此仅将其用作解决方法并使用内联文档清楚地标记它

    以下代码是为默认的 Swing 外观(金属)制作的。如果你想使用另一个 L&F,你需要交换自定义 UI 扩展的类,并且可能做一些其他的调整。这对于分发特定的 L&F 会变得很棘手(可能会迫使您使用反射和委托)。
    (如果您还想使图像居中,请参阅 this answer。)

    代码:
    (对不起,奇怪的评论包装,不知道我的日食有什么问题。)

    设置用户界面:

    comboBox.setUI(new WrapComboBoxUI(3)); // 3 columns
    

    WrapComboBoxUI的源码:

    import javax.swing.JComponent;
    import javax.swing.JList;
    import javax.swing.JPopupMenu;
    import javax.swing.JScrollPane;
    import javax.swing.SwingUtilities;
    import javax.swing.plaf.ComponentUI;
    import javax.swing.plaf.basic.ComboPopup;
    import javax.swing.plaf.metal.MetalComboBoxUI;
    
    public class WrapComboBoxUI extends MetalComboBoxUI {
    
        private int columnCount;
    
        public WrapComboBoxUI() {
            this(0);
        }
    
        /**
         * @param columnCount
         *            the amount of items to render on one row. <br/>
         *          A value of 0 or less will cause the UI to fit as many items
         *            into one row as possible.
         */
        public WrapComboBoxUI(int columnCount) {
            this.columnCount = columnCount;
        }
    
        public static ComponentUI createUI(JComponent c) {
            return new WrapComboBoxUI();
        }
    
        @Override
        protected ComboPopup createPopup() {
            ComboPopup created = super.createPopup();
            try {
                if (created instanceof JPopupMenu) {
                    JPopupMenu popup = (JPopupMenu) created;
                    JScrollPane scroll = (JScrollPane) popup.getComponent(0);
                    JList<?> elementList = (JList<?>) scroll.getViewport().getView();
                    elementList.setLayoutOrientation(JList.HORIZONTAL_WRAP);
                    elementList.setVisibleRowCount(-1);
    
                    new Thread() {
                        @Override
                        public void run() {
                            while (true) {
                                try {
                                    int fixedWidth = -1;
                                    if (columnCount > 0) {
                                        int width = elementList.getWidth() - elementList.getInsets().left - elementList.getInsets().right;
                                        fixedWidth = width / columnCount;
                                    }
                                    boolean changed = false;
                                    if (fixedWidth < 0 && elementList.getFixedCellWidth() >= 0 || fixedWidth >= 0 && elementList.getFixedCellWidth() < 0) {
                                        // if changed from not fixed to fixed or
                                        // other way around
                                        changed = true;
                                    } else if (fixedWidth > 0 && fixedWidth - elementList.getFixedCellWidth() > 1) {
                                        // if width itself changed, ignoring slight
                                        // changes
                                        changed = true;
                                    }
                                    final int width = fixedWidth;
    
                                    // no need to loop again before this is done, so
                                    // we wait
                                    if (changed)
                                        SwingUtilities.invokeAndWait(() -> elementList.setFixedCellWidth(width));
    
                                    sleep(100);
                                } catch (Throwable e) {
                                    // ignored
                                }
                            }
                        };
                    }.start();
                }
            } catch (Throwable e) {
                System.err.println("Failed to customize ComboBoxUI:");
                e.printStackTrace();
            }
            return created;
        }
    }
    

    【讨论】:

    • 答案很有帮助,但物品被压成较窄的形状,所以我接受了camickr的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-02
    相关资源
    最近更新 更多