如何安排 JComboBox 项目
How to arrange JComboBox item
我有一个包含 9 个图像项的 JComboBox。我怎样才能将它们排列成 3*3?
我希望我的物品这样排列
试了google好几天了,不知道这道题的关键词是什么。任何建议表示赞赏。感谢您阅读我的问题。
编辑:
感谢大家的反馈。
我正在制作一个地图编辑器,可以将地图元素放在一起。
The editor.
把石板路布置成3*3比较直观。用户可以很容易地知道哪些元素相互匹配。
我不一定使用组合框。我也考虑过使用按钮,但我认为按钮会浪费 space 的纬度。因为我以后会有更多的地图元素。
可以通过给 JComboBox
自定义 UI 来做到这一点。然而,UI 至少在我的情况下是一团糟,因此 仅将其用作解决方法,并使用内联文档明确标记为 。
以下代码是为默认的 Swing 外观(金属)编写的。如果你想使用另一个 L&F 你需要交换 class 自定义 UI 正在扩展并且可能做一些其他的调整。对于特定于分发的 L&F 这将变得棘手(可能会迫使您使用反射和委托)。
(如果您还想将图像居中,请参阅 this answer。)
代码:
(抱歉奇怪的评论包装,不知道我的日食有什么问题。)
设置UI:
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;
}
}
组合框的弹出窗口使用 JList 组件来显示项目。
您可以访问和更改 JList 的方向以包装项目:
Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
BasicComboPopup popup = (BasicComboPopup)child;
JList list = popup.getList();
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(3);
这将允许您使用 up/down 键浏览项目。
要支持使用 left/right 键进行导航,您需要向组合框添加额外的 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。它具有允许您控制弹出窗口的 size/behaviour 的功能。您将使用:
BoundsPopupMenuListener listener = new BoundsPopupMenuListener(true, false);
comboBox.addPopupMenuListener( listener );
我有一个包含 9 个图像项的 JComboBox。我怎样才能将它们排列成 3*3?
我希望我的物品这样排列
试了google好几天了,不知道这道题的关键词是什么。任何建议表示赞赏。感谢您阅读我的问题。
编辑:
感谢大家的反馈。 我正在制作一个地图编辑器,可以将地图元素放在一起。 The editor. 把石板路布置成3*3比较直观。用户可以很容易地知道哪些元素相互匹配。
我不一定使用组合框。我也考虑过使用按钮,但我认为按钮会浪费 space 的纬度。因为我以后会有更多的地图元素。
可以通过给 JComboBox
自定义 UI 来做到这一点。然而,UI 至少在我的情况下是一团糟,因此 仅将其用作解决方法,并使用内联文档明确标记为 。
以下代码是为默认的 Swing 外观(金属)编写的。如果你想使用另一个 L&F 你需要交换 class 自定义 UI 正在扩展并且可能做一些其他的调整。对于特定于分发的 L&F 这将变得棘手(可能会迫使您使用反射和委托)。
(如果您还想将图像居中,请参阅 this answer。)
代码:
(抱歉奇怪的评论包装,不知道我的日食有什么问题。)
设置UI:
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;
}
}
组合框的弹出窗口使用 JList 组件来显示项目。
您可以访问和更改 JList 的方向以包装项目:
Object child = comboBox.getAccessibleContext().getAccessibleChild(0);
BasicComboPopup popup = (BasicComboPopup)child;
JList list = popup.getList();
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(3);
这将允许您使用 up/down 键浏览项目。
要支持使用 left/right 键进行导航,您需要向组合框添加额外的 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。它具有允许您控制弹出窗口的 size/behaviour 的功能。您将使用:
BoundsPopupMenuListener listener = new BoundsPopupMenuListener(true, false);
comboBox.addPopupMenuListener( listener );