java-JComboBox防止弹出窗口关闭
作者:互联网
我需要在组合框中提供一些禁用的项目.除了防止在单击禁用的项目后关闭组合框之外,所有其他方法都工作正常.
这是我的代码:
import java.awt.Component;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
import javax.swing.plaf.basic.ComboPopup;
public class DisabledCombo {
public static void main(String[] args) {
final DisabledSupportComboModel model = new DisabledSupportComboModel();
model.addElement(new Item("First element"));
model.addElement(new Item("Second element"));
model.addElement(new Item("Disabled", false));
model.addElement(new Item("Fourth element"));
final JComboBox<Item> itemCombo = new JComboBox<DisabledCombo.Item>(model);
itemCombo.setRenderer(new DisabledSupportComboRenderer());
final ComboPopup popup = (ComboPopup) itemCombo.getUI().getAccessibleChild(itemCombo, 0);
final JList<?> l = popup.getList();
final MouseListener[] listeners = l.getMouseListeners();
for (final MouseListener ml : listeners) {
l.removeMouseListener(ml);
System.out.println("remove listener: " + ml);
}
System.out.println("Number of listeners: " + l.getMouseListeners().length);
l.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(MouseEvent e) {
System.out.println("Release");
final int idx = l.locationToIndex(e.getPoint());
if (idx >= 0 && l.getModel().getElementAt(idx) instanceof Item) {
final Item itm = (Item) l.getModel().getElementAt(idx);
if (!itm.isEnabled()) {
e.consume();
}
}
}
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("Click");
final int idx = l.locationToIndex(e.getPoint());
if (idx >= 0 && l.getModel().getElementAt(idx) instanceof Item) {
final Item itm = (Item) l.getModel().getElementAt(idx);
if (!itm.isEnabled()) {
e.consume();
}
}
}
});
for (final MouseListener ml : listeners) {
l.addMouseListener(ml);
}
final JFrame frm = new JFrame("Combo test");
frm.add(itemCombo);
frm.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frm.pack();
frm.setVisible(true);
}
private static class Item {
private final Object value;
private final boolean enabled;
public Item(Object aValue) {
value = aValue;
enabled = true;
}
public Item(Object aValue, boolean isEnabled) {
value = aValue;
enabled = isEnabled;
}
public Object getValue() {
return value;
}
public boolean isEnabled() {
return enabled;
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
return null == value? null : value.toString();
}
}
private static class DisabledSupportComboModel extends DefaultComboBoxModel<Item> {
/**
* {@inheritDoc}
*/
@Override
public void setSelectedItem(Object anObject) {
if (anObject instanceof Item) {
if (((Item) anObject).isEnabled()) {
super.setSelectedItem(anObject);
}
} else {
super.setSelectedItem(anObject);
}
}
}
private static class DisabledSupportComboRenderer extends BasicComboBoxRenderer {
/**
* {@inheritDoc}
*/
@Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof Item) {
if (((Item) value).isEnabled()) {
setForeground(isSelected? list.getSelectionForeground() : list.getForeground());
setBackground(isSelected? list.getSelectionBackground() : list.getBackground());
} else {
setForeground(UIManager.getColor("Label.disabledForeground"));
setBackground(list.getBackground());
}
} else {
setForeground(isSelected? list.getSelectionForeground() : list.getForeground());
setBackground(isSelected? list.getSelectionBackground() : list.getBackground());
}
return this;
}
}
}
我的问题是,我得到mouseReleased事件,但没有mouseClicked事件.获取mouseClicked事件的唯一方法是使用Toolkit类为鼠标事件注册AWTEventListener.但这真的很丑.由于最终会在弹出窗口中滚动窗格,因此使用setPopupVisible(true)再次显示弹出窗口的方法也很困难(实际的组合框可以包含大约30个条目,因此我需要保存滚动条值以在以下位置恢复下拉列表)相同的位置).有人可以建议我,如何防止组合弹出窗口关闭?
解决方法:
>这是我的尝试:
>覆盖JComboBox#setPopupVisible(boolean)而不是使用JList#addMouseListener(…)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DisabledCombo2 {
public static JComponent makeUI() {
DisabledSupportComboModel model = new DisabledSupportComboModel();
model.addElement(new Item("First element"));
model.addElement(new Item("Second element"));
model.addElement(new Item("Disabled", false));
model.addElement(new Item("Fourth element"));
JComboBox<Item> itemCombo = new JComboBox<Item>(model) {
//@see http://java-swing-tips.blogspot.jp/2010/03/non-selectable-jcombobox-items.html
private boolean isDisableIndex;
@Override public void setPopupVisible(boolean v) {
if (!v && isDisableIndex) {
//Do nothing(prevent the combo popup from closing)
isDisableIndex = false;
} else {
super.setPopupVisible(v);
}
}
@Override public void setSelectedObject(Object o) {
if (o instanceof Item && !((Item) o).isEnabled()) {
isDisableIndex = true;
} else {
super.setSelectedObject(o);
}
}
@Override public void setSelectedIndex(int index) {
Object o = getItemAt(index);
if (o instanceof Item && !((Item) o).isEnabled()) {
isDisableIndex = true;
} else {
super.setSelectedIndex(index);
}
}
};
itemCombo.setRenderer(new DisabledSupportComboRenderer());
return itemCombo;
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI() {
JFrame f = new JFrame("Combo test2");
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(makeUI());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class Item {
private final Object value;
private final boolean enabled;
public Item(Object aValue) {
value = aValue;
enabled = true;
}
public Item(Object aValue, boolean isEnabled) {
value = aValue;
enabled = isEnabled;
}
public Object getValue() {
return value;
}
public boolean isEnabled() {
return enabled;
}
@Override public String toString() {
return null == value ? null : value.toString();
}
}
class DisabledSupportComboModel extends DefaultComboBoxModel<Item> {
@Override public void setSelectedItem(Object anObject) {
if (anObject instanceof Item) {
if (((Item) anObject).isEnabled()) {
super.setSelectedItem(anObject);
}
} else {
super.setSelectedItem(anObject);
}
}
}
class DisabledSupportComboRenderer extends DefaultListCellRenderer {
@Override public Component getListCellRendererComponent(
JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof Item) {
if (((Item) value).isEnabled()) {
setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
setBackground(isSelected ? list.getSelectionBackground() : list.getBackground());
} else {
setForeground(UIManager.getColor("Label.disabledForeground"));
setBackground(list.getBackground());
}
} else {
setForeground(isSelected ? list.getSelectionForeground() : list.getForeground());
setBackground(isSelected ? list.getSelectionBackground() : list.getBackground());
}
return this;
}
}
标签:jcombobox,swing,java 来源: https://codeday.me/bug/20191028/1954753.html