【问题标题】:How to check for multiple keys at once using keyTyped(event e)如何使用 keyTyped(event e) 一次检查多个键
【发布时间】:2023-01-20 01:33:37
【问题描述】:

我有以下代码:

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
import javax.swing.event.*;

@SuppressWarnings("serial")
public class MyList
  extends JFrame
  implements ActionListener, ListSelectionListener, KeyListener
{
    static MyList mylist = new MyList();

    public static void main(String[] args)
    {
        // TODO Auto-generated method stub

        JFrame frame = new JFrame();
        frame.setSize(600, 800);
        frame.setDefaultCloseOperation(3);

        JPanel panel = new JPanel();

        JLabel title = new JLabel("<html><body><h1>To-Do-List</h1></body></html>");
        title.setPreferredSize(new Dimension(600, 80));
        title.setHorizontalAlignment(JLabel.CENTER);

        /*
            title.setOpaque(true);
            title.setBackground(Color.cyan);
        */

        /*
            JTextField newTask = new JTextField();
            newTask.setHorizontalAlignment(JTextField.CENTER);
            newTask.setPreferredSize(new Dimension(400, 40));
        */

        JTextArea newTask_field = new JTextArea(3, 1);
        newTask_field.setPreferredSize(new Dimension(400, 80));
        newTask_field.setLineWrap(true);
        newTask_field.setWrapStyleWord(true);

        JScrollPane newTask = new JScrollPane(newTask_field);
        newTask.setPreferredSize(new Dimension(400, 80));

        JButton confirm = new JButton("Add");
        confirm.setHorizontalAlignment(JButton.CENTER);
        confirm.setEnabled(false);

        DefaultListModel<String> listModel = new DefaultListModel<>();
        //listModel.addElement("");

        JList<String> done = new JList<String>(listModel);
        done.setPreferredSize(new Dimension(200, 400));

        DefaultListModel<String> listModel2 = new DefaultListModel<>();

        JList<String> notDoneYet = new JList<String>(listModel2);
        notDoneYet.setPreferredSize(new Dimension(200, 400));

        panel.add(title);
        //panel.add(newTask);
        panel.add(newTask);
        panel.add(mylist.createEmptySpace(new JLabel(), 600, 40));
        panel.add(confirm);
        panel.add(mylist.createEmptySpace(new JLabel(), 600, 0));
        panel.add(done);
        panel.add(mylist.createEmptySpace(new JLabel(), 100, 400));
        panel.add(notDoneYet);
        frame.add(panel);
        frame.setVisible(true);


        //-------------------------------//

        newTask.setFocusable(true);
        newTask_field.setFocusable(true);

        if(newTask_field.getText().equals(""))
        {
            //Unused if-statement
        }

        newTask.addKeyListener(new KeyListener()
            {
                @Override
                public void keyTyped(KeyEvent e)
                {
                    // TODO Auto-generated method stub
                    if(e.getKeyCode() == KeyEvent.VK_A)
                    {

                    }
                }

                @Override
                public void keyReleased(KeyEvent e)
                {
                    // TODO Auto-generated method stub
                }

                @Override
                public void keyPressed(KeyEvent e)
                {
                    // TODO Auto-generated method stub
                }
            });

    }

    //Method createEmptySpace(JLabel(), int, int) which works.
}

现在,我希望它在每次按下打印字符(a-z、1-9、0、*、+、# 等特殊符号)的键时运行 keyTyped 事件。 (此外,我想在按下 Enter、Backspace 或 Delete 后检查 JTextArea 是否为空)。问题是,做一个常规的 if-else 或 switch-case-statement 是荒谬的。想象一下,执行 26+10+dontKnowHowMuch 条件来检查像这样的每个键。有没有办法让它变短,这样我就不需要那样拉伸它了?


更新:我将以下代码写入 KeyListener:

newTask_field.addKeyListener(new KeyListener()
    {
        @Override
        public void keyTyped(KeyEvent e)
        {
            // TODO Auto-generated method stub
            if(e.getKeyCode() == KeyEvent.VK_A)
            {
                confirm.setEnabled(true);
                newTask_field.setText(newTask_field.getText() + e.getKeyCode());
            }
            if(e.getKeyCode() == KeyEvent.VK_ALPHANUMERIC)
            {
                System.out.println("Alphanumeric sign");
                confirm.setEnabled(true);
                newTask_field.setText(newTask_field.getText() + e.getKeyChar());
            }
            if(e.getKeyChar()==KeyEvent.VK_UNDEFINED)
            {
                System.out.println("Undefined");
            }
        }

        @Override
        public void keyReleased(KeyEvent e)
        {
            // TODO Auto-generated method stub

            if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE ||
               e.getKeyCode() == KeyEvent.VK_DELETE     ||
               e.getKeyCode() == KeyEvent.VK_ENTER      ||
               e.getKeyCode() == KeyEvent.VK_SPACE      ||
               e.getKeyCode() == KeyEvent.VK_TAB        ||
               e.getKeyCode() == KeyEvent.VK_CIRCUMFLEX ||
               e.getKeyCode() == KeyEvent.VK_DEAD_ACUTE ||
               e.getKeyCode() == KeyEvent.VK_DEAD_GRAVE)
            {
                if (newTask_field.getText().isBlank())
                {
                    confirm.setEnabled(false);
                }
            }

            if(e.getKeyCode() == KeyEvent.VK_UNDEFINED)
            {
                System.out.println("Undefined");
            }
        }

        @Override
        public void keyPressed(KeyEvent e)
        {
            // TODO Auto-generated method stub
        }
    });

而且无论我在 JTextArea 中键入什么,也无论 KeyListener 是用于 newTask 还是用于 newTask_field,都不会发生任何事情。标志出现在 JTextArea 中,但 KeyListener 什么也不做。任何想法为什么?

【问题讨论】:

  • 如果你只想得到输入的字符,你可以做e.getText()。如果您需要测试每个字符,那么我认为最简洁的方法是执行 switch()/case:
  • 我需要在哪里写e.getText()?根据 Eclipse,对于此 KeyListener 中的 e,getText() 甚至不存在。
  • 正在考虑javaFX,抱歉。您可以按照 MDH 的建议调用 e.getKeyChar()。它会给你按下的键的字符串值

标签: java jscrollpane jtextarea keylistener


【解决方案1】:

从您提供的信息来看,您似乎需要像 PropertyChangeListener() 这样的东西。

newTask_field.addPropertyChangeListener(new PropertyChangeListener() {
            
            @Override
            public void propertyChange(PropertyChangeEvent evt) {
                if(evt.getNewValue().equals("")) {
                
                    confirm.setEnabled(false);
                }else {
                    confirm.setEnabled(true);
                }
            }
        });

更新:

或者,结果是为了操纵 Swing JTextField 中的文本属性更改,您需要使用 addDocumentListener()

newTask_field.getDocument().addDocumentListener(new DocumentListener() {
            
            @Override
            public void removeUpdate(DocumentEvent e) {
                if(newTask_field.getText().isBlank()) {
                    confirm.setEnabled(false);
                }
                
            }
            
            @Override
            public void insertUpdate(DocumentEvent e) {
                confirm.setEnabled(true);
                
            }
            
            @Override
            public void changedUpdate(DocumentEvent e) {
                confirm.setEnabled(true);
                
            }
        });

【讨论】:

  • 我需要对此代码进行编辑吗?因为无论我是把它加到keyReleased 还是keyTyped 上,或者我只是把PropertyChangeListener 写在main 方法里而不是写在KeyListener 里,它什么都不做。
  • 我已经更新了我的答案。我希望它能解决你的问题
  • 我不得不将 txt.getText().equals("") 替换为 newTask_field.getText().isBlank(),但后来成功了。谢谢!
  • 那是代码中的错误......我会编辑并修复它
  • “更新”不属于答案(这就是the revision history 的用途)。答案应该就像是现在写的一样。
【解决方案2】:

快速查看 https://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyEvent.html 会发现“getKeyChar()”-Method(https://docs.oracle.com/javase/7/docs/api/java/awt/event/KeyEvent.html#getKeyChar()),它返回按下的键的字符。

所以你可以使用:

newTask_field.setText(newTas_field.getText() + e.getKeyChar());

至于进入,退格键删除,在那里你只需检查,如果你按下那些并执行你的操作。

因此,您的 keyTyped-Body 可能/应该如下所示:

if ((e.getKeyCode() == KeyEvent.ENTER || e.getKeyCode() == KeyEvent.BACK_SPACE || e.getKeyCode() == KeyEvent.DELETE) && newTask_field.getText().Equals("")) {
    //do your stuff
    return;
}
newTask_field.setText(newTas_field.getText() + e.getKeyChar());

在自己测试代码后,我发现了问题,即您将侦听器添加到 newTask。在我将监听器添加到 newTask_field 而不是 newTask 之后,它工作正常。

超出范围:也许为 main-Method 创建一个单独的 Main-class,并将 MyList 作为一个没有 main-Method 的类。然后在构造函数中创建所有对象并从那里继续。

【讨论】:

  • 要么我不知道在哪里使用它,要么它没有帮助。我不需要函数来打印 JTextArea 中的文本。当我在那里写的时候,这是自己发生的,我什至不需要为此使用 KeyListener。现在,如果 JTextArea 中有文本,我希望启用 JButton,如果它为空/空白,则禁用。该程序必须检查它是否有内容或者它是否为空/清空,并且每次我按下按钮时它都必须检查,因为每次我这样做它都可能改变。这是如何运作的?
  • 好的,这有助于解释您到底想要什么。因此,对于您编辑的代码,您到底在做什么以及正在发生什么?您是否也尝试过将 KeyListener-Methods 实现到您拥有的类,而不是 JTextArea?
  • 使用我更新的代码,我将 KeyListener 添加到 JTextArea 或 JScrollpane - 两者都不做 - 并尝试了几个 if(e.getKeyCode()==KeyEvent.VK_Something){} 语句,但没有成功。我尝试将 A-Z、1-9、0 和特殊符号键添加到 keyTyped,并将 noText 键(如 Backspace、Enter、Space、Delete、Tab)添加到 keyReleased。
  • 使用对我有用的解决方案编辑了我的答案。
猜你喜欢
  • 2011-12-13
  • 2015-09-25
  • 2010-11-20
  • 2016-12-27
  • 1970-01-01
  • 1970-01-01
  • 2019-08-01
  • 1970-01-01
相关资源
最近更新 更多