如果不是 keyEvents,我应该为屏幕键盘使用什么事件侦听器?

What event listener should I use for on-screen keyboard if not keyEvents?

提问人:Rica Jacutina 提问时间:12/22/2020 最后编辑:Rica Jacutina 更新时间:12/23/2020 访问量:289

问:

我的 java swing 程序中有这样的代码:

  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());
                }
            });
        }
    });

它的功能是显示数据库中的名称,就像在文本字段上键入的名称一样。一旦用户开始键入,它就会显示出来。

喜欢这个:enter image description here

这在使用硬键盘时效果很好。但我的问题是我必须为这个程序使用屏幕键盘/虚拟键盘,而 KeyListener 无法使用它。现在我不知道我应该使用什么类型的事件侦听器。我尝试了 MouseListener,但它也不起作用。我希望有办法。我的项目真的需要这个。请帮帮我。

这是我的屏幕键盘代码(在同一类上,它在不同的类中具有更长的代码):

   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) {
            
        }
    });
    

下面是 DialogVirtualKeyboardReal 的图片:enter image description here

按键由 JButtons 制成。


编辑: 我按照@Abra的说明尝试了 DocumentListener。

键盘弹出,但在文本字段中键入 1 个字母后消失,并且弹出文本字段下方的名称。

即使我从虚拟键盘打字,comboFilter 也会出现,这很好。但我希望它同时执行,在虚拟键盘上打字时,应该会出现 comboFilter。

另一件事是我的数据库有错误。

这是我创建的代码:

     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());
            }});
        }           });

错误是:

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

comboFilter() 代码为:

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();
} 
}

我知道我解释的方式很难理解。请多多包涵。你们可能会问进一步的问题,以更好地理解我的问题。多谢!

Java Swing 事件 jtextfield 屏幕键盘

评论

0赞 Rica Jacutina 12/22/2020
它是一个JDialog,它是一个Swing Window。是的,它是 DialogVirtualKeyboardReal。
0赞 Rica Jacutina 12/22/2020
我添加了虚拟键盘@Abra的图片,是的,按键是 JButtons
0赞 Abra 12/22/2020
因此,当用户“按下”虚拟键盘上的一个键时,您希望您的应用程序以与他在 中输入字母相同的方式做出反应,对吗?其实这其实是编辑器组件的一个可编辑的,对吗?JTextFieldJTextFieldJComboBox
0赞 Rica Jacutina 12/22/2020
是的。完全。对不起,我无法很好地解释。
1赞 David Kroukamp 12/23/2020
发布一些重现您的问题的代码,以便您可以更快地获得更好的帮助。

答:

1赞 David Kroukamp 12/23/2020 #1

所以我做了一个小例子来帮助你,但在此之前:

  1. 您的 SQL 错误“连接过多”,您可能希望在打开与数据库连接的所有地方都这样做,如下所示:con.close()

     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. 代码(对作者没有冒犯不是最好的,因为它不能很好地满足键盘不是模的情况),所以你不能在打字时显示对话框,除非你让它成为模态,即传递到构造函数(这是我的例子所做的),或者对实际的, 但这是一个全新的话题。DialogVirtualKeyboardRealtrueDialogVirtualKeyboardRealDialogVirtualKeyboardReal

  3. 由于我上面的说法,在您键入时显示弹出窗口是没有意义的,因为它可能会覆盖键盘。JComboBox

综上所述,我希望这对您有所帮助(我的方法只是模拟响应,就好像它是来自数据库的结果一样):comboFilter

enter image description here

测试应用.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();
        }
    }
}

评论

0赞 Rica Jacutina 1/3/2021
#1 对我不起作用。程序冻结。因为 documentListener 不断从 mysql 数据库中获取名称。我怎样才能阻止它这样做?就像按键的工作原理一样