Auto suggested combobox in JFrame - java

I use the following code for retrieve the data into combobox. How to change Jcombobox into Auto suggested combobox . It means when I press A the words which are start with A that will show in the items field in combobox.
public void combo(){
try{
GCS.GContnStr();
TmpFlxTSt= GCS.GCotnStr.createStatement();
String select = "Select StudName from studentmaster";
TmpFlxTRs = TmpFlxTSt.executeQuery(select);
while(TmpFlxTRs.next())
{
String TmpOb1=TmpFlxTRs.getString("StudName");
TmpOb1.toString();
cbx.addItem(TmpOb1);
cbx.setMaximumRowCount(1);
}

Try to use Combobox component from package org.jdesktop.swingx.autocomplete, maven repository here

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import javax.swing.plaf.basic.*;
class Test
{
private JComboBox_ cb = null;
public Test() {
JFrame fr=new JFrame("TEST ComboBox");
JPanel p = new JPanel();
p.setLayout( new BorderLayout() );
String[] ss = new String[]
{ "112","1123","1124","1134",
"first",
"second",
"third",
"third 1 before",
"third 2",
"third 1 after",
"third quarter",
"fourth",
"fourth and more",
"fourth and more and more"
};
fr.getContentPane().add(p);
cb = new JComboBox_(ss);
p.add("South",cb);
p.add("Center",new JButton("test combo box"));
fr.pack();
fr.show();
}
public static void main( String[] args ) {
Test test=new Test();
}
}
class JComboBox_ extends JComboBox {
public int caretPos=0;
public JTextField tf=null;
public JComboBox_(final Object items[]) {
super(items);
this.setEditor(new BasicComboBoxEditor());
this.setEditable(true);
}
public void setSelectedIndex(int ind) {
super.setSelectedIndex(ind);
tf.setText(getItemAt(ind).toString());
tf.setSelectionEnd(caretPos+tf.getText().length());
tf.moveCaretPosition(caretPos);
// tf.setSelectionStart(caretPos);
}
public void setEditor(ComboBoxEditor anEditor) {
super.setEditor(anEditor);
if (anEditor.getEditorComponent() instanceof JTextField) {
tf=(JTextField)anEditor.getEditorComponent();
tf.addKeyListener(new KeyAdapter()
{
public void keyReleased( KeyEvent ev )
{
char key=ev.getKeyChar();
if (! (Character.isLetterOrDigit(key)||Character.isSpaceChar(key) )) return;
String s = tf.getText();
caretPos=tf.getCaretPosition();
String text="";
try {
text=tf.getText(0,caretPos);
}
catch (Exception ex) {
ex.printStackTrace();
}
int n=getItemCount();
for (int i=0; i<n; i++) {
int ind=((String)getItemAt(i)).indexOf(text);
if (ind==0) {
setSelectedIndex(i);
return;
}
}
}
} );
}
}
}

Related

Keybinding not working for Some Keys like Insert,Delete

I'm trying to bind a shortcut for JTable It's working fine for Alphabets but not for Keys like Insert,Delete,Space etc.
For Ex the below code is working for Ctrl+I or whatever alphabet but If I go for Ctrl+Insert it's not working why is that?
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.table.DefaultTableModel;
public class NewClass {
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(NewClass.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(createTable()), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static JTable createTable() {
DefaultTableModel tmodel = new DefaultTableModel(3, 5);
JTable table = new JTable(tmodel);
table.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK), "Insert");
//Not working for VK_INSERT or VK_DELETE or VK_SPACE
table.getActionMap().put("Insert", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Insert Action");
}
});
return table;
}
}
Update 1
It's not working when using WHEN_IN_FOCUSED_WINDOW but working fine if I go for WHEN_FOCUSED or WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
required WHEN_ANCESTOR_OF_FOCUSED_COMPONENT as corect setting for focus (hidden behind JScrolPanes JViewport)
JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
The component contains (or is) the component that has the focus. This input map is commonly used for a composite component — a
component whose implementation depends on child components. For
example, JTables make all their bindings using
WHEN_ANCESTOR_OF_FOCUSED_COMPONENT so that if the user is editing, the
up-arrow key (for example) still changes the selected cell.
then all KeyEvent combinations from OPs question and comments works me correctly in Win7 / Win10, Java7 / Java8, from deleted post by MadProgrammer too ( users_rep > 10k )
AFAIK there is restiction, with numbers of modifiers, if is > 2, then CTRL + ALT + SHIFT + Whatever is possible to catch from AWTEventListener or from very complicated KeyListener
code for simulation in SSCCE /MCVE form
.
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.table.DefaultTableModel;
public class NewClass {
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info
: javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException |
IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(
NewClass.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.add(new JScrollPane(createTable()), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 500);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static JTable createTable() {
DefaultTableModel tmodel = new DefaultTableModel(3, 5);
JTable table = new JTable(tmodel);
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_MASK), "Insert");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, KeyEvent.CTRL_MASK), "Insert");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, KeyEvent.CTRL_MASK), "Insert");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK), "Insert");
table.getActionMap().put("Insert", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Action from JTable");
}
});
return table;
}
}
code made by Rob (camickr), print out the KeyBindings (sorry I haven't a link to his and Darryls code ...)
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
import javax.swing.filechooser.*;
public class KeyBindings implements ItemListener {
private static final String PACKAGE = "javax.swing.";
private static final String[] COLUMN_NAMES = {"Action", "When Focused",
"When In Focused Window", "When Ancestor"};
private static String selectedItem;
private JComponent contentPane;
private JMenuBar menuBar;
private JTable table;
private JComboBox comboBox;
private Hashtable<String, DefaultTableModel> models;
public KeyBindings() {
models = new Hashtable<String, DefaultTableModel>();
contentPane = new JPanel(new BorderLayout());
contentPane.add(buildNorthComponent(), BorderLayout.NORTH);
contentPane.add(buildCenterComponent(), BorderLayout.CENTER);
resetComponents();
}
public JComponent getContentPane() {
return contentPane;
}
public JMenuBar getMenuBar() {
if (menuBar == null) {
menuBar = createMenuBar();
}
return menuBar;
}
private JComponent buildNorthComponent() {
comboBox = new JComboBox();
JLabel label = new JLabel("Select Component:");
label.setDisplayedMnemonic('S');
label.setLabelFor(comboBox);
JPanel panel = new JPanel();
panel.setBorder(new EmptyBorder(15, 0, 15, 0));
panel.add(label);
panel.add(comboBox);
return panel;
}
private String checkForUIKey(String key) {
if (key.endsWith("UI") && key.indexOf(".") == -1) {
String componentName = key.substring(0, key.length() - 2);
if (componentName.equals("PopupMenuSeparator")
|| componentName.equals("ToolBarSeparator")
|| componentName.equals("DesktopIcon")) {
return null;
} else {
return componentName;
}
}
return null;
}
private JComponent buildCenterComponent() {
DefaultTableModel model = new DefaultTableModel(COLUMN_NAMES, 0);
table = new JTable(model) {
private static final long serialVersionUID = 1L;
#Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
table.setAutoCreateColumnsFromModel(false);
table.getColumnModel().getColumn(0).setPreferredWidth(200);
table.getColumnModel().getColumn(1).setPreferredWidth(200);
table.getColumnModel().getColumn(2).setPreferredWidth(200);
table.getColumnModel().getColumn(3).setPreferredWidth(200);
Dimension d = table.getPreferredSize();
d.height = 350;
table.setPreferredScrollableViewportSize(d);
table.getTableHeader().setFocusable(true);
return new JScrollPane(table);
}
public void resetComponents() {
models.clear();
Vector<String> comboBoxItems = new Vector<String>(50);
UIDefaults defaults = UIManager.getLookAndFeelDefaults();
for (Object key : defaults.keySet()) {
String componentName = checkForUIKey(key.toString());
if (componentName != null) {
comboBoxItems.add(componentName);
}
}
Collections.sort(comboBoxItems);
comboBox.removeItemListener(this);
comboBox.setModel(new DefaultComboBoxModel(comboBoxItems));
comboBox.setSelectedIndex(-1);
comboBox.addItemListener(this);
comboBox.requestFocusInWindow();
if (selectedItem != null) {
comboBox.setSelectedItem(selectedItem);
}
}
private JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
menuBar.add(createFileMenu());
menuBar.add(createLAFMenu());
return menuBar;
}
private JMenu createFileMenu() {
JMenu menu = new JMenu("Application");
menu.setMnemonic('A');
menu.addSeparator();
menu.add(new ExitAction());
return menu;
}
private JMenu createLAFMenu() {
ButtonGroup bg = new ButtonGroup();
JMenu menu = new JMenu("Look & Feel");
menu.setMnemonic('L');
String lafId = UIManager.getLookAndFeel().getID();
UIManager.LookAndFeelInfo[] lafInfo = UIManager.getInstalledLookAndFeels();
for (int i = 0; i < lafInfo.length; i++) {
String laf = lafInfo[i].getClassName();
String name = lafInfo[i].getName();
Action action = new ChangeLookAndFeelAction(laf, name);
JRadioButtonMenuItem mi = new JRadioButtonMenuItem(action);
menu.add(mi);
bg.add(mi);
if (name.equals(lafId)) {
mi.setSelected(true);
}
}
return menu;
}
#Override
public void itemStateChanged(ItemEvent e) {
String componentName = (String) e.getItem();
changeTableModel(getClassName(componentName));
selectedItem = componentName;
}
private String getClassName(String componentName) {
if (componentName.equals("TableHeader")) {
return PACKAGE + "table.JTableHeader";
} else {
return PACKAGE + "J" + componentName;
}
}
private void changeTableModel(String className) {
DefaultTableModel model = models.get(className);
if (model != null) {
table.setModel(model);
return;
}
model = new DefaultTableModel(COLUMN_NAMES, 0);
table.setModel(model);
models.put(className, model);
JComponent component = null;
try {// Hack so I don't have to sign the jar file for usage in Java Webstart
if (className.endsWith("JFileChooser")) {
component = new JFileChooser(new DummyFileSystemView());
} else {
Object o = Class.forName(className).newInstance();
component = (JComponent) o;
}
} catch (Exception e) {
Object[] row = {e.toString(), "", "", ""};
model.addRow(row);
return;
}
ActionMap actionMap = component.getActionMap();
Object[] keys = actionMap.allKeys();
if (keys == null) {
Object[] row = {"No actions found", "", "", ""};
model.addRow(row);
return;
}
for (int i = 0; i < keys.length; i++) {
Object key = keys[i];
if (key instanceof String) {
continue;
} else {
keys[i] = "";
}
}
Arrays.sort(keys);
for (int i = 0; i < keys.length; i++) {
Object key = keys[i];
if (key != "") {
Object[] row = {key, "", "", ""};
model.addRow(row);
}
}
updateModelForInputMap(model, 1,
component.getInputMap(JComponent.WHEN_FOCUSED));
updateModelForInputMap(model, 2,
component.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW));
updateModelForInputMap(model, 3,
component.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT));
}
private void updateModelForInputMap(TableModel model, int column, InputMap inputMap) {
if (inputMap == null) {
return;
}
KeyStroke[] keys = inputMap.allKeys();
if (keys == null) {
return;
}
Hashtable<Object, String> actions = new Hashtable<Object, String>(keys.length);
for (int i = 0; i < keys.length; i++) {
KeyStroke key = keys[i];
Object actionName = inputMap.get(key);
Object value = actions.get(actionName);
if (value == null) {
actions.put(actionName, key.toString().replace("pressed ", ""));
} else {
actions.put(actionName, value + ", " + key.toString().replace("pressed ", ""));
}
}
for (int i = 0; i < model.getRowCount(); i++) {
String o = actions.get(model.getValueAt(i, 0));
if (o != null) {
model.setValueAt(o.toString(), i, column);
}
}
}
class ChangeLookAndFeelAction extends AbstractAction {
private static final long serialVersionUID = 1L;
private String laf;
protected ChangeLookAndFeelAction(String laf, String name) {
this.laf = laf;
putValue(Action.NAME, name);
putValue(Action.SHORT_DESCRIPTION, getValue(Action.NAME));
}
#Override
public void actionPerformed(ActionEvent e) {
try {
JMenuItem mi = (JMenuItem) e.getSource();
JPopupMenu popup = (JPopupMenu) mi.getParent();
JRootPane rootPane = SwingUtilities.getRootPane(popup.getInvoker());
Component c = rootPane.getContentPane().getComponent(0);
rootPane.getContentPane().remove(c);
UIManager.setLookAndFeel(laf);
KeyBindings bindings = new KeyBindings();
rootPane.getContentPane().add(bindings.getContentPane());
SwingUtilities.updateComponentTreeUI(rootPane);
rootPane.requestFocusInWindow();
} catch (Exception ex) {
System.out.println("Failed loading L&F: " + laf);
System.out.println(ex);
}
}
}
class ExitAction extends AbstractAction {
private static final long serialVersionUID = 1L;
public ExitAction() {
putValue(Action.NAME, "Exit");
putValue(Action.SHORT_DESCRIPTION, getValue(Action.NAME));
putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_X));
}
#Override
public void actionPerformed(ActionEvent e) {
System.exit(0);
}
}
class DummyFileSystemView extends FileSystemView {
#Override
public File createNewFolder(File containingDir) {
return null;
}
#Override
public File getDefaultDirectory() {
return null;
}
#Override
public File getHomeDirectory() {
return null;
}
}
private static void createAndShowGUI() {
KeyBindings application = new KeyBindings();
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame("Key Bindings");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setJMenuBar(application.getMenuBar());
frame.getContentPane().add(application.getContentPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
/*try {
SynthLookAndFeel laf = new SynthLookAndFeel();
UIManager.setLookAndFeel(laf);
KeyBindings bindings = new KeyBindings();
} catch (UnsupportedLookAndFeelException ex) {
Logger.getLogger(KeyBindings.class.getName()).log(Level.SEVERE, null, ex);
} */
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
createAndShowGUI();
}
});
}
}
without selection
Delete Action from JTable
Insert Action from JTable
Space Action from JTable
I Action from JTable
after cell is selected
Delete Action from JTable
Insert Action from JTable
Space Action from JTable
I Action from JTable
from code, for correctness is required (otherwise there is bunch of unfilteres events, but completed for testing purposes) to test for CTRL && Whatever is Pressed insideAWTEventListener
import java.awt.AWTEvent;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
public class NewClass {
private JFrame frame = new JFrame();
private DefaultTableModel tmodel = new DefaultTableModel(3, 5);
private JTable table = new JTable(tmodel);
public NewClass() {
frame.add(new JScrollPane(createTable()), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocation(150, 150);
frame.setVisible(true);
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
#Override
public void eventDispatched(AWTEvent event) {
if (event instanceof KeyEvent) {
KeyEvent ke = (KeyEvent) event;
Component comp = ke.getComponent();
if (comp instanceof JTable) {
System.out.println(comp);
} else if (comp instanceof JScrollPane) {
System.out.println(comp);
} else if (comp instanceof JViewport) {
System.out.println(comp);
} else if (comp instanceof JFrame) {
System.out.println(comp);
} else {
System.out.println(comp);
}
}
}
}, AWTEvent.KEY_EVENT_MASK);
}
public JTable createTable() {
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, KeyEvent.CTRL_MASK), "Delete");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_INSERT, KeyEvent.CTRL_MASK), "Insert");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, KeyEvent.CTRL_MASK), "Space");
table.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
KeyStroke.getKeyStroke(KeyEvent.VK_I, KeyEvent.CTRL_MASK), "I");
table.getActionMap().put("Delete", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Delete Action from JTable");
}
});
table.getActionMap().put("Insert", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Insert Action from JTable");
}
});
table.getActionMap().put("Space", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Space Action from JTable");
}
});
table.getActionMap().put("I", new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("I Action from JTable");
}
});
return table;
}
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info
: javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException |
IllegalAccessException |
javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(
NewClass.class.getName()).log(
java.util.logging.Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new NewClass();
}
});
}
}

How to create a multi-layer JComboBox

I'm creating a simulator using Java Swing. I used JComboBox to display units of utilities such as "KW, KL, KM" etc to measure Power, Water and distance. It's simple to add bunch of items to a JComboBox. User select a unit and the JFrame will save the selection when a "save" button is clicked.
JComboBox comboBox = new JComboBox();
for(ValueUnits u: ValueUnits.values()){
comboBox.addItem(u.returnUnits());
}
comboBox.setSelectedIndex(-1);
unitColumn.setCellEditor(new DefaultCellEditor(comboBox));
Now I want to create an multi-layer JComboBox (perhaps JMenu?). The function of such should behave as a multi-layer JMenu. When the JComboBox is clicked, it will show the first layer - category such as "Electricity, Water, Distance...", Then when mouse hover over Electricity, a list of Electricity units such as "KW, MW, W ..." will show. These collections are fetched from Enumerations. I wonder what's the most correct way to create such component.
Thank you so much world!
Maybe use 2 combo boxes? That is you select a value in the first and the units are displayed in the second:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class ComboBoxTwo extends JPanel implements ActionListener
{
private JComboBox<String> mainComboBox;
private JComboBox<String> subComboBox;
private Hashtable<String, String[]> subItems = new Hashtable<String, String[]>();
public ComboBoxTwo()
{
String[] items = { "Select Item", "Color", "Shape", "Fruit" };
mainComboBox = new JComboBox<String>( items );
mainComboBox.addActionListener( this );
// prevent action events from being fired when the up/down arrow keys are used
mainComboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
add( mainComboBox );
// Create sub combo box with multiple models
subComboBox = new JComboBox<String>();
subComboBox.setPrototypeDisplayValue("XXXXXXXXXX"); // JDK1.4
add( subComboBox );
String[] subItems1 = { "Select Color", "Red", "Blue", "Green" };
subItems.put(items[1], subItems1);
String[] subItems2 = { "Select Shape", "Circle", "Square", "Triangle" };
subItems.put(items[2], subItems2);
String[] subItems3 = { "Select Fruit", "Apple", "Orange", "Banana" };
subItems.put(items[3], subItems3);
}
public void actionPerformed(ActionEvent e)
{
String item = (String)mainComboBox.getSelectedItem();
Object o = subItems.get( item );
if (o == null)
{
subComboBox.setModel( new DefaultComboBoxModel() );
}
else
{
subComboBox.setModel( new DefaultComboBoxModel( (String[])o ) );
}
}
private static void createAndShowUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( new ComboBoxTwo() );
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
Use It...
public class ComboLayer extends javax.swing.JPanel {
String Category1 = null;
String Category2 = null;
String Category3 = null;
Hashtable<String, String> hsItems;
public ComboLayer() {
this.hsItems = new Hashtable<>();
hsItems.put("Main", "Power,Water,Distance");
hsItems.put("Power", "KW,MW,W");
hsItems.put("Water", "ML,L,KL");
hsItems.put("Distance", "CM,M,KM");
initComponents();
String[] item = hsItems.get("Main").split(",");
for (String i : item) {
cmbItem.addItem(i);
}
cmbItem.addItem("Back");
cmbItem.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
String selectText = null;
selectText = (String) cmbItem.getSelectedItem();
Enumeration enmKeys = hsItems.keys();
while (enmKeys.hasMoreElements()) {
String sKey = (String) enmKeys.nextElement();
if (selectText.equalsIgnoreCase("back")) {
if (hsItems.get(sKey).contains(cmbItem.getItemAt(0).toString())) {
Enumeration enumkeysBack = hsItems.keys();
while (enumkeysBack.hasMoreElements()) {
String sKeyBack = (String) enumkeysBack.nextElement();
if (hsItems.get(sKeyBack).contains(sKey)) {
String[] item = hsItems.get(sKeyBack).split(",");
cmbItem.removeAllItems();
for (String i : item) {
cmbItem.addItem(i);
}
if (!sKeyBack.equalsIgnoreCase("Main")) {
cmbItem.addItem("Back");
}
break;
}
}
}
} else if (sKey.contains(selectText)) {
String[] item = hsItems.get(sKey).split(",");
cmbItem.removeAllItems();
for (String i : item) {
cmbItem.addItem(i);
}
if (!sKey.equalsIgnoreCase("Main")) {
cmbItem.addItem("Back");
}
break;
}
}
}
});
}
public static void main(String... arg) {
ComboLayer cmbLyr = new ComboLayer();
JDialog dg = new JDialog();
dg.add(cmbLyr);
dg.setVisible(true);
}
Here's a combo with the effect of a custom popup of JMenu's. The actual popup is hidden, and a second popup is displayed when appropriate.
Upon selection of a JMenuItem, the combo is populated with just that one item, displayed in breadcrumb format.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
import javax.swing.plaf.metal.*;
public class JMenuComboBoxDemo implements Runnable
{
private Map<String, String[]> menuData;
private JComboBox<String> combo;
private AbstractButton arrowButton;
private JPopupMenu popupMenu;
private List<String> flattenedData;
public static void main(String[] args)
{
SwingUtilities.invokeLater(new JMenuComboBoxDemo());
}
public JMenuComboBoxDemo()
{
menuData = new HashMap<String, String[]>();
menuData.put("Colors", new String[]{"Black", "Blue"});
menuData.put("Flavors", new String[]{"Lemon", "Lime"});
popupMenu = new JPopupMenu();
popupMenu.setBorder(new MatteBorder(1, 1, 1, 1, Color.DARK_GRAY));
List<String> categories = new ArrayList<String>(menuData.keySet());
Collections.sort(categories);
// copy of the menuData, flattened into a List
flattenedData = new ArrayList<String>();
for (String category : categories)
{
JMenu menu = new JMenu(category);
for (String itemName : menuData.get(category))
{
menu.add(createMenuItem(itemName));
flattenedData.add(category + " > " + itemName);
}
popupMenu.add(menu);
}
combo = new JComboBox<String>();
combo.setPrototypeDisplayValue("12345678901234567890");
combo.setUI(new EmptyComboBoxUI());
for (Component comp : combo.getComponents())
{
if (comp instanceof AbstractButton)
{
arrowButton = (AbstractButton) comp;
}
}
arrowButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
setPopupVisible(! popupMenu.isVisible());
}
});
combo.addMouseListener(new MouseAdapter()
{
#Override
public void mouseClicked(MouseEvent e)
{
setPopupVisible(! popupMenu.isVisible());
}
});
}
public void run()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container c = frame.getContentPane();
c.setLayout(new FlowLayout());
c.add(new JLabel("Options"));
c.add(combo);
frame.setSize(300, 200);
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
/*
* Toggle the visibility of the custom popup.
*/
private void setPopupVisible(boolean visible)
{
if (visible)
{
popupMenu.show(combo, 0, combo.getSize().height);
}
else
{
popupMenu.setVisible(false);
}
}
/*
* Create a JMenuItem whose listener will display
* the item in the combo.
*/
private JMenuItem createMenuItem(final String name)
{
JMenuItem item = new JMenuItem(name);
item.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
setComboSelection(name);
}
});
return item;
}
/*
* Search for the given name in the flattened list of menu items.
* If found, add that item to the combo and select it.
*/
private void setComboSelection(String name)
{
Vector<String> items = new Vector<String>();
for (String item : flattenedData)
{
/*
* We're cheating here: if two items have the same name
* (Fruit->Orange and Color->Orange, for example)
* the wrong one may get selected. This should be more sophisticated
* (left as an exercise to the reader)
*/
if (item.endsWith(name))
{
items.add(item);
break;
}
}
combo.setModel(new DefaultComboBoxModel<String>(items));
if (items.size() == 1)
{
combo.setSelectedIndex(0);
}
}
/*
* Prevents the default popup from being displayed
*/
class EmptyComboBoxUI extends MetalComboBoxUI
{
#Override
protected ComboPopup createPopup()
{
BasicComboPopup thePopup = (BasicComboPopup) super.createPopup();
thePopup.setPreferredSize(new Dimension(0,0)); // oh, the horror!
return thePopup;
}
}
}

How to set Key Binding to editable JTable in swing?

I want to remove selected row of JTable by pressing only Delete button.
When I press Delete, selected cell becomes editable and my action(on jframe) does not receive KeyEvent.
Please, run this demo to see the effect:
public class TestTableKeyBinding extends JFrame {
// private static final int MASK = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
private JTable table;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TestTableKeyBinding test = new TestTableKeyBinding();
test.setVisible(true);
}
});
}
TestTableKeyBinding() {
super();
initUI();
addKeyBindings();
}
private void initUI() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] headers = new String[] { "apples", "bananas" };
String[][] data = new String[][] { { "1", "2" }, { "4", "6" }, { "5", "7" }, { "1", "3" }, { "2", "11" } };
table = new JTable(data, headers);
table.setRowSelectionAllowed(true);
this.add(new JScrollPane(table));
this.pack();
this.setSize(new Dimension(300, 400));
}
private void addKeyBindings() {
// root maps
InputMap im = this.getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
ActionMap am = this.getRootPane().getActionMap();
// add custom action
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), "save");
am.put("save", saveAction());
}
private AbstractAction saveAction() {
AbstractAction save = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(TestTableKeyBinding.this.table, "Action Triggered.");
table.editingCanceled(null);
table.editingStopped(null);
int selectedRow = table.getSelectedRow();
if (selectedRow != -1) {
((DefaultTableModel) table.getModel()).removeRow(selectedRow);
}
}
};
return save;
}
}
Thanks for help!
I have tested your code and made some changes as mentioned below. Now it's working fine.
private void addKeyBindings() {
KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
table.getActionMap().put("save", saveAction());
table.getInputMap(JComponent.WHEN_FOCUSED).put(keyStroke, "save");
}
Make one more change as mentioned below
table = new JTable(new DefaultTableModel(data,headers));
otherwise it will result in ClassCastException at below line
((DefaultTableModel) table.getModel()).removeRow(selectedRow);
Here is complete code:
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.table.DefaultTableModel;
public class TestTableKeyBinding extends JFrame {
private JTable table;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TestTableKeyBinding test = new TestTableKeyBinding();
test.setVisible(true);
}
});
}
TestTableKeyBinding() {
super();
initUI();
addKeyBindings();
}
private void initUI() {
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String[] headers = new String[] { "apples", "bananas" };
String[][] data = new String[][] { { "1", "2" }, { "4", "6" }, { "5", "7" }, { "1", "3" },
{ "2", "11" } };
table = new JTable(new DefaultTableModel(data,headers));
table.setRowSelectionAllowed(true);
this.add(new JScrollPane(table));
this.pack();
this.setSize(new Dimension(300, 400));
}
private void addKeyBindings() {
KeyStroke keyStroke = KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0);
table.getActionMap().put("save", saveAction());
table.getInputMap(JComponent.WHEN_FOCUSED).put(keyStroke, "save");
}
private AbstractAction saveAction() {
AbstractAction save = new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(TestTableKeyBinding.this.table, "Action Triggered.");
table.editingCanceled(null);
table.editingStopped(null);
int selectedRow = table.getSelectedRow();
if (selectedRow != -1) {
((DefaultTableModel) table.getModel()).removeRow(selectedRow);
}
}
};
return save;
}
}

jcombobox filter in java - Look and feel independent

I have a simple JComboBox filter code like this :
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class FilterComboBox extends JComboBox {
private List<String> array;
public FilterComboBox(List<String> array) {
super(array.toArray());
this.array = array;
this.setEditable(true);
final JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
comboFilter(textfield.getText());
}
});
}
});
}
public void comboFilter(String enteredText) {
List<String> filterArray= new ArrayList<String>();
for (int i = 0; i < array.size(); i++) {
if (array.get(i).toLowerCase().contains(enteredText.toLowerCase())) {
filterArray.add(array.get(i));
}
}
if (filterArray.size() > 0) {
this.setModel(new DefaultComboBoxModel(filterArray.toArray()));
this.setSelectedItem(enteredText);
this.showPopup();
}
else {
this.hidePopup();
}
}
/* Testing Codes */
public static List<String> populateArray() {
List<String> test = new ArrayList<String>();
test.add("");
test.add("Mountain Flight");
test.add("Mount Climbing");
test.add("Trekking");
test.add("Rafting");
test.add("Jungle Safari");
test.add("Bungie Jumping");
test.add("Para Gliding");
return test;
}
public static void makeUI() {
JFrame frame = new JFrame("Adventure in Nepal - Combo Filter Test");
FilterComboBox acb = new FilterComboBox(populateArray());
frame.getContentPane().add(acb);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) throws Exception {
//UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
makeUI();
}
}
The performance of the combo filter is not so good but it is fine for few data set. My problem is - when I remove the comment UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); to change look and feel, the filter doesn't work. In WindowsLookAndFeel, the combo box only takes single character in it by replacing the previously entered character.
Can you please tell me whats going on? Manoj Shrestha's answer below helps in some way but , can you please provide some other suggestions to achieve combo box filter in Java?
Firstly you are creating new model everytime and then invoking show popup from code which leads to flickering etc. We can modify the model itself. Secondly you set the currently entered text as selected item which seems to have selectAll behavior as noted by others. I have modified the code as follows:
public void comboFilter(String enteredText) {
if (!this.isPopupVisible()) {
this.showPopup();
}
List<String> filterArray= new ArrayList<String>();
for (int i = 0; i < array.size(); i++) {
if (array.get(i).toLowerCase().contains(enteredText.toLowerCase())) {
filterArray.add(array.get(i));
}
}
if (filterArray.size() > 0) {
DefaultComboBoxModel model = (DefaultComboBoxModel) this.getModel();
model.removeAllElements();
for (String s: filterArray)
model.addElement(s);
JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.setText(enteredText);
}
}
Hope it works for you.
very long answer, I think that exelent example about how different Look and Feel have got implemented methods in API and works
KeyListener isn't proper Listener for Swing JComponents, you really to have bothering with KeyBindings,
KeyListener is simple asynchronous,
JComboBox is Compound JComponent, then there is required override internal JComponents, all output from KeyListener must be wrapped into invokeLater(), notice I can create event from coumpond JComponents that twice invokeLater() doesn't returns expected output to the GUI, only Swing Timer with Swing Action can do that correctly, simple why to bothering wiht that example about wrong way,
code
import java.awt.Component;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
public class ComboBoxHoverOver {
private JComboBox combo = new JComboBox();
public ComboBoxHoverOver() {
combo.setPrototypeDisplayValue("XXXXXXXXXXXXXXXXXXXXXX");
combo.setRenderer(new ComboToolTipRenderer(combo));
combo.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
//System.out.println(combo.getSelectedItem().toString());
}
});
combo.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
//System.out.println(combo.getSelectedItem().toString());
}
});
combo.addItem("");
combo.addItem("Long text 4");
combo.addItem("Long text 3");
combo.addItem("Long text 2");
combo.addItem("Long text 1");
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(combo);
f.pack();
f.setVisible(true);
}
private class ComboToolTipRenderer extends BasicComboBoxRenderer {
private static final long serialVersionUID = 1L;
private JComboBox combo;
private JList comboList;
ComboToolTipRenderer(JComboBox combo) {
this.combo = combo;
}
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(
list, value, index, isSelected, cellHasFocus);
if (comboList == null) {
comboList = list;
KeyAdapter listener = new KeyAdapter() {
#Override
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_UP) {
int x = 5;
int y = comboList.indexToLocation(comboList.getSelectedIndex()).y;
System.out.println(comboList.getSelectedIndex());
}
}
};
combo.addKeyListener(listener);
combo.getEditor().getEditorComponent().addKeyListener(listener);
}
if (isSelected) {
//System.out.println(value.toString());
}
return this;
}
}
public static void main(String[] args) throws ClassNotFoundException,
InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
ComboBoxHoverOver comboBoxHoverOver = new ComboBoxHoverOver();
}
});
}
}
JComboBox is Compound JComponent, then there is required override BasicComboBoxUI, please sorry I lazy to write and simulating too much longer code as code from first point
otherwise all effort from above two point are useless and contraproductive, nothing else, only DOT
please can someone to test follows code in *nix and apple OS X
from my Java6 WinXP compo (all important is hidden in the used methods, enless kudos for anonymous author from former Sun Microsystems)
Substance L&F
WindowsLookAndFeel L&F
Nimbus L&F
Metal L&F
from Java Classes
main
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import org.pushingpixels.substance.api.skin.SubstanceOfficeSilver2007LookAndFeel;
public class AutoCompleteTextField {
private static JFrame frame = new JFrame();
private ArrayList<String> listSomeString = new ArrayList<String>();
private Java2sAutoTextField someTextField = new Java2sAutoTextField(listSomeString);
private ArrayList<String> listSomeAnotherString = new ArrayList<String>();
private Java2sAutoComboBox someComboBox = new Java2sAutoComboBox(listSomeAnotherString);
public AutoCompleteTextField() {
listSomeString.add("-");
listSomeString.add("Snowboarding");
listSomeString.add("Rowing");
listSomeString.add("Knitting");
listSomeString.add("Speed reading");
listSomeString.add("Pool");
listSomeString.add("None of the above");
//
listSomeAnotherString.add("-");
listSomeAnotherString.add("XxxZxx Snowboarding");
listSomeAnotherString.add("AaaBbb Rowing");
listSomeAnotherString.add("CccDdd Knitting");
listSomeAnotherString.add("Eee Fff Speed reading");
listSomeAnotherString.add("Eee Fff Pool");
listSomeAnotherString.add("Eee Fff None of the above");
//
someTextField.setFont(new Font("Serif", Font.BOLD, 16));
someTextField.setForeground(Color.black);
someTextField.setBackground(Color.orange);
someTextField.setName("someTextField");
someTextField.setDataList(listSomeString);
//
someComboBox.setPrototypeDisplayValue("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
someComboBox.setFont(new Font("Serif", Font.BOLD, 16));
someComboBox.setForeground(Color.black);
someComboBox.setBackground(Color.YELLOW);
someComboBox.getEditor().selectAll();
someComboBox.getEditor().getEditorComponent().setBackground(Color.YELLOW);
((JTextField) someComboBox.getEditor().getEditorComponent()).setDisabledTextColor(Color.black);
someComboBox.setName("someComboBox");
someComboBox.setDataList(listSomeAnotherString);
//
frame.setLayout(new GridLayout(0, 1, 10, 10));
frame.add(someTextField);
frame.add(someComboBox);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocation(100, 100);
frame.pack();
frame.setVisible(true);
//
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
someTextField.setText("-");
someComboBox.getEditor().setItem(0);
someComboBox.getEditor().selectAll();
someTextField.grabFocus();
someTextField.requestFocus();
someTextField.setText(someTextField.getText());
someTextField.selectAll();
}
});
}
public static void main(String[] args) {
/*SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(new SubstanceOfficeSilver2007LookAndFeel());
SwingUtilities.updateComponentTreeUI(frame);
} catch (UnsupportedLookAndFeelException e) {
throw new RuntimeException(e);
}
}
});*/
/*try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
System.out.println(info.getName());
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (UnsupportedLookAndFeelException e) {
// handle exception
} catch (ClassNotFoundException e) {
// handle exception
} catch (InstantiationException e) {
// handle exception
} catch (IllegalAccessException e) {
// handle exception
}*/
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
AutoCompleteTextField aCTF = new AutoCompleteTextField();
}
});
}
}
AutoComboBox
import java.awt.event.ItemEvent;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.plaf.basic.BasicComboBoxEditor;
public class Java2sAutoComboBox extends JComboBox {
private static final long serialVersionUID = 1L;
private AutoTextFieldEditor autoTextFieldEditor;
private boolean isFired;
private class AutoTextFieldEditor extends BasicComboBoxEditor {
private Java2sAutoTextField getAutoTextFieldEditor() {
return (Java2sAutoTextField) editor;
}
AutoTextFieldEditor(java.util.List<String> list) {
editor = new Java2sAutoTextField(list, Java2sAutoComboBox.this);
}
}
public Java2sAutoComboBox(java.util.List<String> list) {
isFired = false;
autoTextFieldEditor = new AutoTextFieldEditor(list);
setEditable(true);
setModel(new DefaultComboBoxModel(list.toArray()) {
private static final long serialVersionUID = 1L;
#Override
protected void fireContentsChanged(Object obj, int i, int j) {
if (!isFired) {
super.fireContentsChanged(obj, i, j);
}
}
});
setEditor(autoTextFieldEditor);
}
public boolean isCaseSensitive() {
return autoTextFieldEditor.getAutoTextFieldEditor().isCaseSensitive();
}
public void setCaseSensitive(boolean flag) {
autoTextFieldEditor.getAutoTextFieldEditor().setCaseSensitive(flag);
}
public boolean isStrict() {
return autoTextFieldEditor.getAutoTextFieldEditor().isStrict();
}
public void setStrict(boolean flag) {
autoTextFieldEditor.getAutoTextFieldEditor().setStrict(flag);
}
public java.util.List<String> getDataList() {
return autoTextFieldEditor.getAutoTextFieldEditor().getDataList();
}
public void setDataList(java.util.List<String> list) {
autoTextFieldEditor.getAutoTextFieldEditor().setDataList(list);
setModel(new DefaultComboBoxModel(list.toArray()));
}
void setSelectedValue(Object obj) {
if (isFired) {
return;
} else {
isFired = true;
setSelectedItem(obj);
fireItemStateChanged(new ItemEvent(this, 701, selectedItemReminder, 1));
isFired = false;
return;
}
}
#Override
protected void fireActionEvent() {
if (!isFired) {
super.fireActionEvent();
}
}
}
AutoTextField
import java.util.List;
import javax.swing.JTextField;
import javax.swing.text.*;
public class Java2sAutoTextField extends JTextField {
private static final long serialVersionUID = 1L;
private List<String> dataList;
private boolean isCaseSensitive;
private boolean isStrict;
private Java2sAutoComboBox autoComboBox;
public class AutoDocument extends PlainDocument {
private static final long serialVersionUID = 1L;
#Override
public void replace(int i, int j, String s, AttributeSet attributeset)
throws BadLocationException {
super.remove(i, j);
insertString(i, s, attributeset);
}
#Override
public void insertString(int i, String s, AttributeSet attributeset)
throws BadLocationException {
if (s == null || "".equals(s)) {
return;
}
String s1 = getText(0, i);
String s2 = getMatch(s1 + s);
int j = (i + s.length()) - 1;
if (isStrict && s2 == null) {
s2 = getMatch(s1);
j--;
} else if (!isStrict && s2 == null) {
super.insertString(i, s, attributeset);
return;
}
if (autoComboBox != null && s2 != null) {
autoComboBox.setSelectedValue(s2);
}
super.remove(0, getLength());
super.insertString(0, s2, attributeset);
setSelectionStart(j + 1);
setSelectionEnd(getLength());
}
#Override
public void remove(int i, int j) throws BadLocationException {
int k = getSelectionStart();
if (k > 0) {
k--;
}
String s = getMatch(getText(0, k));
if (!isStrict && s == null) {
super.remove(i, j);
} else {
super.remove(0, getLength());
super.insertString(0, s, null);
}
if (autoComboBox != null && s != null) {
autoComboBox.setSelectedValue(s);
}
try {
setSelectionStart(k);
setSelectionEnd(getLength());
} catch (Exception exception) {
}
}
}
public Java2sAutoTextField(List<String> list) {
isCaseSensitive = false;
isStrict = true;
autoComboBox = null;
if (list == null) {
throw new IllegalArgumentException("values can not be null");
} else {
dataList = list;
init();
return;
}
}
Java2sAutoTextField(List<String> list, Java2sAutoComboBox b) {
isCaseSensitive = false;
isStrict = true;
autoComboBox = null;
if (list == null) {
throw new IllegalArgumentException("values can not be null");
} else {
dataList = list;
autoComboBox = b;
init();
return;
}
}
private void init() {
setDocument(new AutoDocument());
if (isStrict && dataList.size() > 0) {
setText(dataList.get(0).toString());
}
}
private String getMatch(String s) {
for (int i = 0; i < dataList.size(); i++) {
String s1 = dataList.get(i).toString();
if (s1 != null) {
if (!isCaseSensitive
&& s1.toLowerCase().startsWith(s.toLowerCase())) {
return s1;
}
if (isCaseSensitive && s1.startsWith(s)) {
return s1;
}
}
}
return null;
}
#Override
public void replaceSelection(String s) {
AutoDocument _lb = (AutoDocument) getDocument();
if (_lb != null) {
try {
int i = Math.min(getCaret().getDot(), getCaret().getMark());
int j = Math.max(getCaret().getDot(), getCaret().getMark());
_lb.replace(i, j - i, s, null);
} catch (Exception exception) {
}
}
}
public boolean isCaseSensitive() {
return isCaseSensitive;
}
public void setCaseSensitive(boolean flag) {
isCaseSensitive = flag;
}
public boolean isStrict() {
return isStrict;
}
public void setStrict(boolean flag) {
isStrict = flag;
}
public List<String> getDataList() {
return dataList;
}
public void setDataList(List<String> list) {
if (list == null) {
throw new IllegalArgumentException("values can not be null");
} else {
dataList = list;
return;
}
}
}
EDIT
output from Win7 64b / Java7
Metal L&F
Windows L&F (funny empty white space near Button in JComboBox)
Nimbus L&F
feel free for edit(s)
This component is called autocomplete and is included in a so called swing extensions porject.
Just have a look at: http://swingx.java.net/
There is a webstart: http://swinglabs-demos.java.net/demos/swingxset6/swingxset.jnlp
Autocomplete is the Menu to select. Have fun and less error prone code :)
obviously the glitch is in the textfield component used. What happens is, when windows look and feel is used , the text in this component is selected just as using the line "textfield.selectAll();", and hence when you type anything else the selected text is cleared form the textfield component. So in the below code the caret position of this component is adjusted. This is how it works, first store the current caret position of text field in a variable "currentCaretPosition", then move the caret position to the beginning in the text in the component. After filtering restoring the caret position back to the "currentCaretPosition" variable value. I hope it works as you want it to.
The refined code is given below:-
/****Beginning of code****/
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
public class FilterComboBox extends JComboBox {
private List<String> array;
private int currentCaretPosition=0;
public FilterComboBox(List<String> array) {
super(array.toArray());
this.array = array;
this.setEditable(true);
final JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent ke) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
currentCaretPosition=textfield.getCaretPosition();
if(textfield.getSelectedText()==null)
{
textfield.setCaretPosition(0);
comboFilter(textfield.getText());
textfield.setCaretPosition(currentCaretPosition);
}
}
});
}
});
}
public void comboFilter(String enteredText) {
List<String> filterArray= new ArrayList<String>();
for (int i = 0; i < array.size(); i++) {
if (array.get(i).toLowerCase().contains(enteredText.toLowerCase())) {
filterArray.add(array.get(i));
}
}
if (filterArray.size() > 0) {
this.setModel(new DefaultComboBoxModel(filterArray.toArray()));
this.setSelectedItem(enteredText);
this.showPopup();
}
else {
this.hidePopup();
}
}
/* Testing Codes */
public static List<String> populateArray() {
List<String> test = new ArrayList<String>();
test.add("");
test.add("Mountain Flight");
test.add("Mount Climbing");
test.add("Trekking");
test.add("Rafting");
test.add("Jungle Safari");
test.add("Bungie Jumping");
test.add("Para Gliding");
return test;
}
public static void makeUI() {
JFrame frame = new JFrame("Adventure in Nepal - Combo Filter Test");
FilterComboBox acb = new FilterComboBox(populateArray());
frame.getContentPane().add(acb);
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
public static void main(String[] args) throws Exception {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
makeUI();
}
}
/******* End of code**********/
It looks like, as you mentioned, when user inputs any texts in combobox, the Windows Look & Feel selects (highlights) the entered text. So, when you press another key, it replaces the previous one. So, the solution is not to highlight the entered texts. You can achieve this by adding any one of the following statements in your keylistener.
textfield.setCaretPosition(textfield.getText().length());
OR
textfield.setSelectionStart(textfield.getText().length());
So, your keylistener should look like this :
final JTextField textfield = (JTextField) this.getEditor().getEditorComponent();
textfield.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent ke) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
comboFilter(textfield.getText());
textfield.setCaretPosition(textfield.getText().length());
}
});
}
});

how to add different JComboBox items in a Column of a JTable in Swing

I want to add JComboBox inside a JTable (3,3) on column 1. But in the column 1 , each row will have its own set of ComboBox element.
When I tried to use
table.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(comboBox_Custom));
Each row is being set to same set of ComboBox Values.
But I want each row ComboBox has different items.
example on java2s.com looks like as works and correctly, then for example (I harcoded JComboBoxes for quick example, and add/change for todays Swing)
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.table.*;
public class EachRowEditorExample extends JFrame {
private static final long serialVersionUID = 1L;
public EachRowEditorExample() {
super("EachRow Editor Example");
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
System.out.println(info.getName());
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (UnsupportedLookAndFeelException e) {
// handle exception
} catch (ClassNotFoundException e) {
// handle exception
} catch (InstantiationException e) {
// handle exception
} catch (IllegalAccessException e) {
// handle exception
}
DefaultTableModel dm = new DefaultTableModel();
dm.setDataVector(new Object[][]{{"Name", "MyName"}, {"Gender", "Male"}, {"Color", "Fruit"}}, new Object[]{"Column1", "Column2"});
JTable table = new JTable(dm);
table.setRowHeight(20);
JComboBox comboBox = new JComboBox();
comboBox.addItem("Male");
comboBox.addItem("Female");
comboBox.addComponentListener(new ComponentAdapter() {
#Override
public void componentShown(ComponentEvent e) {
final JComponent c = (JComponent) e.getSource();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
c.requestFocus();
System.out.println(c);
if (c instanceof JComboBox) {
System.out.println("a");
}
}
});
}
});
JComboBox comboBox1 = new JComboBox();
comboBox1.addItem("Name");
comboBox1.addItem("MyName");
comboBox1.addComponentListener(new ComponentAdapter() {
#Override
public void componentShown(ComponentEvent e) {
final JComponent c = (JComponent) e.getSource();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
c.requestFocus();
System.out.println(c);
if (c instanceof JComboBox) {
System.out.println("a");
}
}
});
}
});
JComboBox comboBox2 = new JComboBox();
comboBox2.addItem("Banana");
comboBox2.addItem("Apple");
comboBox2.addComponentListener(new ComponentAdapter() {
#Override
public void componentShown(ComponentEvent e) {
final JComponent c = (JComponent) e.getSource();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
c.requestFocus();
System.out.println(c);
if (c instanceof JComboBox) {
System.out.println("a");
}
}
});
}
});
EachRowEditor rowEditor = new EachRowEditor(table);
rowEditor.setEditorAt(0, new DefaultCellEditor(comboBox1));
rowEditor.setEditorAt(1, new DefaultCellEditor(comboBox));
rowEditor.setEditorAt(2, new DefaultCellEditor(comboBox2));
table.getColumn("Column2").setCellEditor(rowEditor);
JScrollPane scroll = new JScrollPane(table);
getContentPane().add(scroll, BorderLayout.CENTER);
setPreferredSize(new Dimension(400, 120));
setLocation(150, 100);
pack();
setVisible(true);
}
public static void main(String[] args) {
EachRowEditorExample frame = new EachRowEditorExample();
frame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}
just add EachRowEditor Class
package com.atos.table.classes;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
public class PartCustomerWindow2 {
public static final Object[][] DATA = { { 1, 2,3, 4,false }, { 5, 6,7, 8 ,true},{ 9, 10,11, 12,true }, { 13, 14,15, 16,true } };
public static final String[] COL_NAMES = { "One", "Two", "Three", "Four",MyTableModel1.SELECT };
JButton but = new JButton("Add");
private JComboBox jcomboBox = null;
private JTextField jTextField = null;
static Object[][] rowData = null;
private JTable table=null;
static JFrame frame = null;
HashMap mp = null;
static int count = 0;
String content = null;
public JTextField getjTextField() {
if(jTextField == null)
{
jTextField = new FMORestrictedTextField(FMORestrictedTextField.JUST_ALPHANUMERIC, 8);
}
mp = new HashMap();
mp.put("arif",2);
mp.put("8",6);
mp.put("12",10);
mp.put("14",16);
mp.put("pk1",22);
mp.put("pk3",23);
jTextField.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent event) {
if(count == 0)
content = jTextField.getText();
// System.out.println(content);
if(mp.containsKey(content))
{
JFrame parent = new JFrame();
JOptionPane.showMessageDialog(parent, "Already Assigned");
}
}
});
return jTextField;
}
public void setjTextField(JTextField jTextField) {
this.jTextField = jTextField;
}
public JComboBox getJcomboBox() {
if(jcomboBox == null)
{
jcomboBox = new JComboBox();
}
return jcomboBox;
}
public void setJcomboBox(JComboBox jcomboBox) {
this.jcomboBox = jcomboBox;
}
private void createAndShowGui(PartCustomerWindow2 ob)
{
/*rowData = new Object[DATA.length][];
for (int i = 0; i < rowData.length; i++) {
rowData[i] = new Object[DATA[i].length + 1];
for (int j = 0; j < DATA[i].length; j++) {
rowData[i][j] = DATA[i][j];
}
rowData[i][DATA[i].length] = Boolean.TRUE;
if(i == 2 || i ==3)
rowData[i][DATA[i].length] = Boolean.FALSE;
}*/
MyTableModel3 tableModel = new MyTableModel3(DATA, COL_NAMES, "My Table", ob);
table = new JTable(tableModel);
//table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
/*table.addFocusListener(new java.awt.event.FocusAdapter() {
public void focusLost(java.awt.event.FocusEvent evt) {
table.getSelectionModel().clearSelection();
}
});*/
TableColumnModel cm = table.getColumnModel();
/*cm.getColumn(2).setCellEditor(new DefaultCellEditor(
new JComboBox(new DefaultComboBoxModel(new String[] {
"Yes",
"No",
"Maybe"
}))));*/
/* String ar1[]= {"aa","aaa","aaaa"};
ob.getJcomboBox().setModel(new DefaultComboBoxModel(ar1));*/
cm.getColumn(2).setCellEditor(new DefaultCellEditor(
ob.getJcomboBox()));
cm.getColumn(3).setCellEditor(new DefaultCellEditor(
ob.getjTextField()));
JScrollPane scrollPane = new JScrollPane();
/* scrollPane.add("Table",table);
scrollPane.add("Button",but);*/
JFrame frame2 = new JFrame();
/* jcomboBox.setPreferredSize(new Dimension(100,20));
textField.setPreferredSize(new Dimension(100,20));
jcomboBox.setEnabled(false);
textField.setEnabled(false);
*/
JScrollPane scrollPane2 = new JScrollPane(but);
but.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(table.getCellEditor() != null)
table.getCellEditor().stopCellEditing();
// TODO Auto-generated method stub
String[][] ar = new String[table.getRowCount()][5];
for(int i =0;i<table.getRowCount();i++)
{
for(int j=0;j<5;j++)
{
DATA[i][j] = table.getValueAt(i,j);
}
System.out.print(table.getValueAt(i,0)+" ");
System.out.print(table.getValueAt(i,1)+" ");
System.out.print(table.getValueAt(i,2)+" ");
System.out.print(table.getValueAt(i,3)+" ");
System.out.println(table.getValueAt(i,4)+" ");
}
System.out.println("*******************");
/*
for(int i=0;i<DATA.length;i++)
{
System.out.print(DATA[i][0]);
System.out.print(DATA[i][1]);
System.out.print(DATA[i][2]);
System.out.print(DATA[i][3]);
boolean check =(Boolean) DATA[i][4];
System.out.println(check);
}*/
}});
frame = new JFrame("PartCustomerWindow2");
//
//JFrame frame = new JFrame();
Container contentPane = frame.getContentPane();
contentPane.setLayout(new BorderLayout());
contentPane.add(new JScrollPane(table), BorderLayout.NORTH);
contentPane.add(but);
//
//frame.setLayout(new FlowLayout());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/* frame.getContentPane().add(scrollPane2);
frame.getContentPane().add(scrollPane3);
frame.getContentPane().add(scrollPane4);*/
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
PartCustomerWindow2 ob = new PartCustomerWindow2();
ob.createAndShowGui(ob);
}
}
#SuppressWarnings("serial")
class MyTableModel3 extends DefaultTableModel {
public static final String SELECT = "select";
String tablename;
PartCustomerWindow2 ob = null;
public MyTableModel3(Object[][] rowData, Object[] columnNames, String tableName,PartCustomerWindow2 ob) {
super(rowData, columnNames);
this.tablename = tableName;
this.ob = ob;
}
#Override
public Class<?> getColumnClass(int columnIndex) {
if (getColumnName(columnIndex).equalsIgnoreCase(SELECT)) {
return Boolean.class;
}
else
return super.getColumnClass(columnIndex);
}
#Override
public boolean isCellEditable(int row, int col) {
JComboBox jb = ob.getJcomboBox();
JTextField jt = ob.getjTextField();
if(((Boolean) getValueAt(row, getColumnCount() - 1)).booleanValue())
{
// jb.setEnabled(false);
jb.removeAllItems();
// System.out.println(jb.getItemCount());
if(row == 0)
{
jb.addItem("arif");
jb.addItem("asif");
jb.addItem("ashik");
jb.addItem("farooq");
jb.addItem("adkh");
}
if(row > 0)
{
jb.addItem("kjhds");
jb.addItem("sdds");
jb.addItem("asdfsdk");
jb.addItem("sdfsdf");
jb.addItem("sdf");
}
/*HashMap mp = new HashMap();
mp.put("arif",2);
mp.put("8",6);
mp.put("12",10);
mp.put("14",16);
mp.put("pk1",22);
mp.put("pk3",23);
*/
/* if(col == 3){
if(mp.containsKey(jt.getText()))
{
System.out.println("Sorry..!! already assigned");
jt.setFocusable(true);
}
jt.setText("");
jt.setEnabled(false);
}*/
}
else
{
// jb.setEnabled(true);
//jt.setEnabled(true);
}
if (col == getColumnCount()-1 ) {
return true;
}
else{
if (getColumnName(4).equalsIgnoreCase(SELECT) && ((Boolean) getValueAt(row, getColumnCount() - 1)).booleanValue())
{
// jb.setEnabled(true);
// jt.setEnabled(true);
return (col == 2 || col == 3);
}
else{
// jb.setEnabled(false);
//jt.setEnabled(false);
return false;
}
}
}
}

Categories