我正在编写一个扩展 JComboBox 的自定义组件。我的问题是,如果我添加或删除一个项目,PopupMenu 不会实现它的大小。因此,例如列表中有 2 个项目,但如果之前有 4 个项目,我在 PopupMenu 中也有 2 个“空”项目。
我发现的唯一解决方法是(在 JIntelligentComboBox.java 第 213 行)
this.setPopupVisible(false);
this.setPopupVisible(true);
但结果将是一个闪烁的 PopupMenu :-(
那么我还能做些什么来刷新/重新绘制 PopupMenu 而不会闪烁?
- 键入“e”
- 按“返回”
- 键入“m”
提前致谢
编辑:我的目标是一个组合框,它的作用类似于 Firefox 或 Chrome 中的地址栏,我想显示包含键入字符的 PopupMenu 的所有项目。
cboxtester.java:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
public class cboxtester extends JFrame {
private DefaultComboBoxModel dcm = new DefaultComboBoxModel(new Object[][] {new Object[] {"Mittagessen", "", 0},
new Object[] {"Essen", "", 0},
new Object[] {"Frühstück", "", 0},
new Object[] {"Abendessen", "", 0}});
private JIntelligentComboBox icb = new JIntelligentComboBox(dcm);
private cboxtester(){
this.add(icb, BorderLayout.CENTER);
this.add(new JButton("bla"), BorderLayout.EAST);
this.pack();
this.setVisible(true);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
cboxtester cbt = new cboxtester();
}
}
JIntelligentComboBox.java:
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Vector;
import javax.swing.ComboBoxEditor;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.DefaultRowSorter;
import javax.swing.JComboBox;
import javax.swing.JList;
import javax.swing.JTextField;
import javax.swing.ListCellRenderer;
import javax.swing.MutableComboBoxModel;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
import javax.swing.plaf.metal.MetalComboBoxEditor;
public class JIntelligentComboBox extends JComboBox {
private ArrayList<Object> itemBackup = new ArrayList<Object>();
/** Initisiert die JIntelligentComboBox */
private void init(){
class searchComboBoxEditor extends BasicComboBoxEditor {
public searchComboBoxEditor(){
super();
}
@Override
public void setItem(Object anObject){
if (anObject == null) {
super.setItem(anObject);
} else {
Object[] o = (Object[]) anObject;
super.setItem(o[0]);
}
}
@Override
public Object getItem(){
return new Object[]{super.getItem(), super.getItem(), 0};
}
}
this.setEditor(new searchComboBoxEditor());
this.setEditable(true);
class searchRenderer extends BasicComboBoxRenderer {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus){
if (index == 0) {
setText("");
this.setPreferredSize(new Dimension(1, 1));
return this;
}
this.setPreferredSize(new Dimension(160, 17));
if (index == list.getModel().getSize() - 1) {
this.setBorder(new EmptyBorder(0, 3, 1, 3));
} else {
this.setBorder(new EmptyBorder(0, 3, 0, 3));
}
Object[] v = (Object[]) value;
//System.out.println(v[0]);
this.setFont(new Font("Arial", Font.PLAIN, 12));
this.setBackground(Color.white);
String s = (String) v[0];
String lowerS = s.toLowerCase();
String sf = (String) v[1];
String lowerSf = sf.toLowerCase();
ArrayList<String> notMatching = new ArrayList<String>();
if (!sf.equals("")){
int fs = -1;
int lastFs = 0;
while ((fs = lowerS.indexOf((String) lowerSf, (lastFs == 0) ? -1 : lastFs)) > -1) {
notMatching.add(s.substring(lastFs, fs));
lastFs = fs + sf.length();
//System.out.println(fs+sf.length());
}
notMatching.add(s.substring(lastFs));
//System.out.println(notMatching);
}
String html = "";
if (notMatching.size() > 1) {
html = notMatching.get(0);
int start = html.length();
int sfl = sf.length();
for (int i = 1; i < notMatching.size(); i++) {
String t = notMatching.get(i);
html += "<b style=\"color: black;\">" + s.substring(start, start + sfl) + "</b>" + t;
start += sfl + t.length();
}
}
System.out.println(index + html);
this.setText("<html><head></head><body style=\"color: gray;\">" + html + "</body></head>");
return this;
}
}
this.setRenderer(new searchRenderer());
// leeres Element oben einfügen
int size = this.getModel().getSize();
Object[] tmp = new Object[this.getModel().getSize()];
for (int i = 0; i < size; i++) {
tmp[i] = this.getModel().getElementAt(i);
itemBackup.add(tmp[i]);
}
this.removeAllItems();
this.getModel().addElement(new Object[]{"", "", 0});
for (int i = 0; i < tmp.length; i++) {
this.getModel().addElement(tmp[i]);
}
// keylistener hinzufügen
this.getEditor().getEditorComponent().addKeyListener(new KeyListener() {
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
searchAndListEntries(((JTextField)JIntelligentComboBox.this.getEditor().getEditorComponent()).getText());
//System.out.println(((JTextField)JIntelligentComboBox.this.getEditor().getEditorComponent()).getText());
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
});
}
public JIntelligentComboBox(){
super();
}
public JIntelligentComboBox(MutableComboBoxModel aModel){
super(aModel);
init();
}
public JIntelligentComboBox(Object[] items){
super(items);
init();
}
public JIntelligentComboBox(Vector<?> items){
super(items);
init();
}
@Override
public MutableComboBoxModel getModel(){
return (MutableComboBoxModel) super.getModel();
}
private void searchAndListEntries(Object searchFor){
ArrayList<Object> found = new ArrayList<Object>();
//System.out.println("sf: "+searchFor);
for (int i = 0; i < this.itemBackup.size(); i++) {
Object tmp = this.itemBackup.get(i);
if (tmp == null || searchFor == null) continue;
Object[] o = (Object[]) tmp;
String s = (String) o[0];
if (s.matches("(?i).*" + searchFor + ".*")){
found.add(new Object[]{((Object[])tmp)[0], searchFor, ((Object[])tmp)[2]});
}
}
this.removeAllItems();
this.getModel().addElement(new Object[] {searchFor, searchFor, 0});
for (int i = 0; i < found.size(); i++) {
this.getModel().addElement(found.get(i));
}
this.setPopupVisible(true);
}
}