当使用“系统”外观时,Java组合框setSelectedItem会出现故障
我正在使用keyTyped listerner模拟Windows的组合框功能,在用户键入编辑框时自动滚动组合列表框。当使用默认的跨平台LookAndFeel时,它工作得很好。 我发现了JComboBox。设置LookAndFeel更改为系统LookAndFeel时的SelectedItem故障:
我是经理。setLookAndFeel(UIManager.getSystemLookAndFeelClassName())
下面的代码在结尾使用setSelectedItem(OrigTypeface)调用来恢复编辑框中的原始文本
使用跨平台的LookAndFeel,当用户键入“abc”时,列表框会逐步显示与列表框中键入的文本匹配的第一项。然而,使用系统LookAndFeel,编辑框中的文本从“a”到“b”再到“c”,最后在文本框中只显示字母“c”,并显示列表框,其中条目以第一个字母“c”开头。实际上,setSelectedItem失败,文本框中出现空白
有人知道解决这个问题的方法吗
getEditor().getEditorComponent().addKeyListener(new KeyAdapter() {
@Override public void keyTyped(KeyEvent ev) {
String OrigTypeface=(String)cb.getEditor().getItem();
if (OrigTypeface==null) OrigTypeface="";
char CurChar=ev.getKeyChar();
String typeface=OrigTypeface + CurChar; character
typeface=typeface.toLowerCase();
if (typeface.length()==0 || (int)CurChar==8) return; // exclude the backspace key
int i,count=cb.getItemCount();
for (i=0;i<count;i++) {
String item=(String)cb.getItemAt(i);
if (item!=null) {
item=item.toLowerCase();
if (item.startsWith(typeface) && cb.getSelectedIndex()!=i) {
int BumpUp=cb.getMaximumRowCount()/2; // normally list-bolx would position the item the end of the list, so we bump its position to the middle
if ((i+BumpUp)<count) cb.setSelectedIndex(i+BumpUp);
cb.setSelectedIndex(i); // select this item
cb.hidePopup(); // hide/show to actually display this item in the scroll list
cb.showPopup();
cb.setSelectedItem(OrigTypeface); // put this item back in the edit box since it gets overridden by the above setSelectedIndex call
break;
}
}
}
}
}
});
下面是一个小的java文件,您可以编译并运行它来重现这个问题。只需在两个组合框中键入“abc”。你会看到左边的那个工作正常,但右边的那个不行
import java.awt.*;
import java.lang.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.print.*;
import java.lang.reflect.Method;
import java.awt.font.*; // to get TextAttribute class
import java.awt.geom.*; // to get AffilineTransform
import java.lang.reflect.Array;
import java.nio.charset.*;
import java.text.*; // to get SimpleDateFormat
import javax.swing.event.*;
import java.awt.datatransfer.*;
import java.awt.image.*;
import javax.print.attribute.standard.*;
import javax.print.attribute.standard.Media.*;
import javax.swing.border.*;
import java.awt.Robot;
import java.util.prefs.*;
import java.awt.dnd.*;
import javax.swing.plaf.ComponentUI;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.basic.BasicComboBoxUI;
public class demo extends JPanel {
OurComboBox cb1;
OurComboBox cb2;
JLabel lbl1;
JLabel lbl2;
public demo() {
super(new GridLayout(2,2));
JLabel lbl1=new JLabel();
lbl1.setPreferredSize(new Dimension(250, 15));
lbl1.setText("ComboBox using cross-platform L&F");
add(lbl1);
JLabel lbl2=new JLabel();
lbl2.setPreferredSize(new Dimension(250, 15));
lbl2.setText("ComboBox using System L&F");
add(lbl2);
cb1=new OurComboBox();
cb1.setPreferredSize(new Dimension(200, 15));
cb1.setLightWeightPopupEnabled(false);
cb1.setEditable(true); // allow edit box
AddComboItems(cb1);
add(cb1);
// change to System LookAndFeel temporarily
try {UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());}
catch (Exception ex) {}
cb2=new OurComboBox();
cb2.setPreferredSize(new Dimension(200, 15));
cb2.setLightWeightPopupEnabled(false);
cb2.setEditable(true); // allow edit box
AddComboItems(cb2);
add(cb2);
// rever back LookAndFeel
try {UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); }
catch (Exception ex) {}
}
// add items to the combo-box
void AddComboItems(OurComboBox cb) {
for (int i=0;i<20;i++) cb.addItem("a"+((Integer)i).toString());
for (int i=0;i<20;i++) cb.addItem("ab"+((Integer)i).toString());
for (int i=0;i<20;i++) cb.addItem("abc"+((Integer)i).toString());
for (int i=0;i<20;i++) cb.addItem("bc"+((Integer)i).toString());
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event dispatch thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//Add content to the window.
frame.add(new demo());
//Display the window.
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
//Schedule a job for the event dispatch thread:
//creating and showing this application's GUI.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Turn off metal's use of bold fonts
UIManager.put("swing.boldMetal", Boolean.FALSE);
createAndShowGUI();
}
});
}
}
class OurComboBox extends JComboBox {
public boolean locked;
public OurComboBox cb;
OurComboBox() {
cb=this; // save so it can be accessed inside the key listerner below
getEditor().getEditorComponent().addKeyListener(new KeyAdapter() { // add key listenr to the editor component
@Override public void keyTyped(KeyEvent ev) {
String OrigTypeface=(String)cb.getEditor().getItem();
if (OrigTypeface==null) OrigTypeface=""; // 20150313
char CurChar=ev.getKeyChar();
String typeface=OrigTypeface + CurChar; // getItem() returns the prviously typed text, getKeyChar()) returns the latest character
typeface=typeface.toLowerCase();
if (typeface.length()==0 || (int)CurChar==8) return; // exclude the backspace key
if ((int)CurChar==0xa) return; // just return for now
else { // scroll the combo-box to show the currently typed typefacee
int i,count=cb.getItemCount();
for (i=0;i<count;i++) {
String item=(String)cb.getItemAt(i);
if (item!=null) {
item=item.toLowerCase();
if (item.startsWith(typeface) && cb.getSelectedIndex()!=i) {
cb.locked=true; // don't process item state changed for this change
if ((i+cb.getMaximumRowCount()/2)<count) cb.setSelectedIndex(i+cb.getMaximumRowCount()/2); // try to move the actual index in the middle because java by default shows the selected index at the bottom
cb.setSelectedIndex(i); // select this item
cb.hidePopup(); // hide/show to actually display this item in the scroll list
cb.showPopup();
cb.setSelectedItem(OrigTypeface); // put this item back in the edit box
cb.locked=false;
break;
}
}
}
}
}
});
}
}
共 (0) 个答案