Java 两个背景和一根线

Java 两个背景和一根线,java,actionlistener,Java,Actionlistener,我想在JTextField中键入一些内容后将其颜色更改为红色,然后在第二次之后返回默认的白色背景。我在监听器之外尝试了这个方法,它很管用,但是当它成为监听器的一部分时,它就不管用了(它只是跳过设置红色)。这对我来说很奇怪 public class Test { JFrame frame; JTextField field; public Test() { frame = new JFrame(); field = new JTextFie

我想在JTextField中键入一些内容后将其颜色更改为红色,然后在第二次之后返回默认的白色背景。我在监听器之外尝试了这个方法,它很管用,但是当它成为监听器的一部分时,它就不管用了(它只是跳过设置红色)。这对我来说很奇怪

public class Test {
    JFrame frame;
    JTextField field;

    public Test() {
        frame = new JFrame();
        field = new JTextField("A");
        field.addKeyListener(new KeyBListener());
        frame.getContentPane().add(field);
        frame.pack();
        frame.setVisible(true);
    } 

    public static void main(String[] args) { new Test(); }

    private class KeyBListener implements KeyListener {
        @Override
        public void keyTyped(KeyEvent e) {

            try {
                field.setBackground(Color.RED);
                Thread.sleep(1000);
                field.setBackground(Color.WHITE);
            } catch (InterruptedException es) { es.printStackTrace(); }

        }

        @Override
        public void keyPressed(KeyEvent e) { }

        @Override
        public void keyReleased(KeyEvent e) { }
    } 
}

尝试创建一个单独的
线程
,该线程侦听
JTextField
上的颜色更改,然后将其更改回来。在这种情况下,至少不会阻塞主线程,尽管我不确定这是最有效的方法

public Main() {
    frame = new JFrame();
    frame.setSize(800, 600);
    field = new JTextField("A");
    field.addKeyListener(new KeyBListener());
    frame.getContentPane().add(field);
    frame.pack();
    frame.setVisible(true);

    new Thread(() -> {
        while(true) {
            if(field.getBackground().equals(Color.RED))
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
            field.setBackground(Color.WHITE);
        }

    }).start();
}

您以前的解决方案是有效的,因为它是从AWT本身执行的

keyTyped()
方法在事件分派thead(EDT)上执行,因此必须将绘制操作移回AWT

查看
SwingUtilities.invokeLater()
(非阻塞)或
SwingUtilities.invokeAndWait()
(阻塞),请参阅


您可以生成一个不同的线程,在其中执行颜色操作。这确保了颜色操纵不会在EDT内部发生

import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class Test {
    JFrame frame;
    JTextField field;
    AtomicBoolean isColorChangeOn = new AtomicBoolean();
    public Test() {
        frame = new JFrame();
        field = new JTextField("A");
        field.addKeyListener(new KeyBListener());
        frame.getContentPane().add(field);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        isColorChangeOn.set(false);
    }

    public static void main(String[] args) {
        new Test();
    }

    private class KeyBListener implements KeyListener {
        @Override
        public void keyTyped(KeyEvent e) {
                if(!isColorChangeOn.get()) {
                    isColorChangeOn.set(true);
                    Runnable setcolor = ()->{
                        try {
                            System.out.println("color changing");
                            field.setBackground(Color.RED);
                            Thread.sleep(1000);
                            field.setBackground(Color.WHITE);
                            isColorChangeOn.set(false);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                    };
                    new Thread(setcolor).start();
                }
        }

        @Override
        public void keyPressed(KeyEvent e) {
        }

        @Override
        public void keyReleased(KeyEvent e) {
        }
    }
}

您需要阅读事件调度线程(EDT)。对于这样的更新,它们必须发生在EDT之外,否则,您将阻止重新绘制显示。是的,不知道是否有其他方法。我想在
监听器中创建一个线程,但每次按键启动一个线程还是有点糟糕。。
import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.concurrent.atomic.AtomicBoolean;

import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.WindowConstants;

public class Test {
    JFrame frame;
    JTextField field;
    AtomicBoolean isColorChangeOn = new AtomicBoolean();
    public Test() {
        frame = new JFrame();
        field = new JTextField("A");
        field.addKeyListener(new KeyBListener());
        frame.getContentPane().add(field);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        isColorChangeOn.set(false);
    }

    public static void main(String[] args) {
        new Test();
    }

    private class KeyBListener implements KeyListener {
        @Override
        public void keyTyped(KeyEvent e) {
                if(!isColorChangeOn.get()) {
                    isColorChangeOn.set(true);
                    Runnable setcolor = ()->{
                        try {
                            System.out.println("color changing");
                            field.setBackground(Color.RED);
                            Thread.sleep(1000);
                            field.setBackground(Color.WHITE);
                            isColorChangeOn.set(false);
                        } catch (InterruptedException e1) {
                            e1.printStackTrace();
                        }
                    };
                    new Thread(setcolor).start();
                }
        }

        @Override
        public void keyPressed(KeyEvent e) {
        }

        @Override
        public void keyReleased(KeyEvent e) {
        }
    }
}