1

I have a code that goes like this in my java swing program:

  JTextField textfield = (JTextField) txtNameID.getEditor().getEditorComponent();
  textfield.addKeyListener(new KeyAdapter() {
        public void keyPressed(KeyEvent ke) {
            
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    comboFilter(textfield.getText());
                }
            });
        }
    });

It's function is to show names from database that's like what is being typed on the textfield. It should show up once the user started typing.

Like this: enter image description here

And this works well when using hard keyboard. But my problem is I have to use an on screen keyboard/virtual keyboard for this program and KeyListener doesn't work with it. Now I don't know what type of event listener I should use. I tried MouseListener but it doesn't work also. I hope there is a way. I really need this for my project. Please kindly help me out.

This is my code for the on-screen keyboard(on the same class, it has a longer code in a different class):

   textfield.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
                  DialogVirtualKeyboardReal dlg = new DialogVirtualKeyboardReal(this, false, textfield);
                     dlg.setLocaleL(locale);
        }
    });
    
     textfield.addMouseListener(new MouseListener() {

        @Override
        public void mousePressed(MouseEvent me) {
            DialogVirtualKeyboardReal dlg = new DialogVirtualKeyboardReal(r, false, textfield);
                     dlg.setLocaleL(locale);
        }

        @Override
        public void mouseReleased(MouseEvent me) {
            
        }

        @Override
        public void mouseEntered(MouseEvent me) {
          
        }

        @Override
        public void mouseExited(MouseEvent me) {
           
        }

        @Override
        public void mouseClicked(MouseEvent me) {
            
        }
    });
    

Here's a picture of the DialogVirtualKeyboardReal: enter image description here

The keys are made of JButtons.


EDITED: I tried DocumentListener following the instructions of @Abra.

The keyboard pops up, but it disappears after 1 letter typed in the textfield and the names below the textfield pops up.

It's good that the comboFilter appears even when I type from virtual keyboard. But I want it to execute simultaneously, while typing on the virtual keyboard, the comboFilter should appear.

Another thing is that it had an error with my database.

This is the code I created:

     JTextField textfield = (JTextField) txtNameID.getEditor().getEditorComponent();
   textfield.getDocument().addDocumentListener(new DocumentListener(){

        @Override
        public void insertUpdate(DocumentEvent de) {
         filter();
        }

        @Override
        public void removeUpdate(DocumentEvent de) {
            filter();
        }

        @Override
        public void changedUpdate(DocumentEvent de) {
            filter();
        }
        public void filter(){
             SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                comboFilter(textfield.getText());
            }});
        }           });

And the error is:

  errorcom.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection,  message from server: "Too many connections"

The comboFilter() code is:

public void comboFilter(String enteredText) {
List<String> filterArray= new ArrayList<String>();

        String lname="";
        String fname= "";
        String mi= "";
        String id= "";

 try{
String str="SELECT * FROM patient_record WHERE firstname  LIKE '"+enteredText+"%' OR lastname  LIKE '"+enteredText+"%' OR patient_id  LIKE '"+enteredText+"%'";
Class.forName("com.mysql.jdbc.Driver");
    String url = "jdbc:mysql://localhost/patient";
    Connection con = DriverManager.getConnection(url,"root","");

 Statement stmt=con.createStatement();
 ResultSet rs=stmt.executeQuery(str);
 while(rs.next()){
  lname=rs.getString("lastname");
  fname= rs.getString("firstname");
  mi= rs.getString("middlename");
  id= rs.getString("patient_id");
  String str1 = lname+", "+fname+" "+mi+". \t"+id;
  filterArray.add(str1);
 }}
catch(Exception ex){
 System.out.println("error"+ex);   
}

if (filterArray.size() > 0) {
    jComboBox1.setModel(new DefaultComboBoxModel(filterArray.toArray()));
    jComboBox1.setSelectedItem(enteredText);
    jComboBox1.showPopup();
}
else {
    jComboBox1.hidePopup();
} 
}

I know the way I explained it is difficult to understand. Please bear with me. You guys may ask for further questions to better understand my question. Thanks a lot!

  • It is a JDialog which is a Swing Window. And yes, it is DialogVirtualKeyboardReal. – Rica Jacutina Dec 22 '20 at 13:15
  • I've added a picture of the virtual keyboard @Abra, yes the keys are JButtons – Rica Jacutina Dec 22 '20 at 13:48
  • So when the user "presses" a key on the virtual keyboard, you want your application to react in the same way as if he entered a letter into the `JTextField`, correct? In fact, this `JTextField` is actually the editor component of an editable `JComboBox`, correct? – Abra Dec 22 '20 at 13:54
  • Yes yes. Exactly. Sorry I couldn't explain it well. – Rica Jacutina Dec 22 '20 at 13:59
  • Looking at the code for the virtual keyboard it has a constructor `DialogVirtualKeyboardReal(java.awt.Frame parent, boolean modal, JTextComponent textComponent)` which accepts a `JTextComponent` I.e. a `JTextField` so I assume it will automatically add keys pressed to the textfield. In your code you initialise the `DialogVirtualKeyboardReal` inside the `ActionListener` of the textfield. This is incorrect simply move the code outside of the `ActionListener ` and I'm sure all will work ? – David Kroukamp Dec 22 '20 at 15:19
  • @DavidKroukamp it doesn't work :( And I only need the virtual keyboard when I click the textfield/combobox. – Rica Jacutina Dec 22 '20 at 15:53
  • 1
    Post some code that reproduces your problem so you can get better help faster. – David Kroukamp Dec 22 '20 at 16:02
  • I've edited my post, could you check it again @DavidKroukamp – Rica Jacutina Dec 22 '20 at 16:12

1 Answers1

1

So I've made a small example to help you, but before that:

  1. Your SQL error "Too many connections", you probbaly want to do con.close() in ALL places you open a connection to the database like this:

     Connection con = null
     try {
         // create the connection and do your database work here
     } catch (Exception ex) {
         // log your exception here
     } finally {
         if (con != null) {
             // finally lets close the connection (event in the event of a exception)
             con.close();
         }
     }
    
  2. The DialogVirtualKeyboardReal code (no offence to the author is not the best as it doesn't cater well for the scenario of the keyboard not being modal), so you cant have the dialog show while typing unless you make it modal i.e. pass true into the DialogVirtualKeyboardReal constructor (which is what my example does), or make changes to the actual DialogVirtualKeyboardReal, but thats a whole new topic.

  3. Because of my above statement it doesnt make sense to show the JComboBox popup as you type as it potentially will cover the keyboard.

With all that said I hope this helps get you started (my comboFilter method simply mocks up a response as if it was a result from the database):

enter image description here

TestApp.java

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class TestApp {

    private JComboBox<String> jComboBox1;
    private final ArrayList<String> listOfNames = new ArrayList<>();

    public TestApp() {
        listOfNames.add("David Kroukamp");
        listOfNames.add("Abra");
        listOfNames.add("Camickr");
        listOfNames.add("Hovercraft Full Of Eels");
        listOfNames.add("Andrew Thompson");
        listOfNames.add("MadProgrammer");
        listOfNames.add("TrashGod");
        listOfNames.add("Gilbert Le Blanc");
        listOfNames.add("mKorbel");
        listOfNames.add("kleopatra");
        listOfNames.add("Reimeus");
        listOfNames.add("StanislavL");
        listOfNames.add("Paul Samsotha");
        listOfNames.add("Guillaume Polet");
        createAndShowGui();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(TestApp::new);
    }

    private void createAndShowGui() {
        JFrame frame = new JFrame("TestApp");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        jComboBox1 = new JComboBox<>(new DefaultComboBoxModel(listOfNames.toArray()));

        JLabel nameLabel = new JLabel("Name:");
        JTextField textField = new JTextField(20);
        textField.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                comboFilter(textField.getText());
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                comboFilter(textField.getText());
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                // plain text components dont fire this
            }
        });

        JButton showKeyboardButton = new JButton("Show Keyboard");
        showKeyboardButton.addActionListener((ActionEvent e) -> {
            new DialogVirtualKeyboardReal(frame, true, textField);
        });

        JPanel panel = new JPanel();
        panel.add(nameLabel);
        panel.add(textField);
        panel.add(showKeyboardButton);

        frame.add(panel, BorderLayout.CENTER);
        frame.add(jComboBox1, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);

        new DialogVirtualKeyboardReal(frame, false, textField);
    }

    public void comboFilter(String enteredText) {
        List<String> filterArray = new ArrayList<>();

        listOfNames.forEach((item) -> {
            if (item.contains(enteredText)) {
                filterArray.add(item);
            }
        });

        if (filterArray.size() > 0) {
            jComboBox1.setModel(new DefaultComboBoxModel(filterArray.toArray()));
            //jComboBox1.showPopup();
        } else {
            //jComboBox1.hidePopup();
        }
    }
}
David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
  • #1 doesn't work for me. The program freezes. Because the documentListener is continuously getting names from mysql database. How can I stop it from doing so? Like how keypressed works – Rica Jacutina Jan 03 '21 at 09:02