简体   繁体   中英

Java swing graphics not updating

I have a java application that uses Swing graphics which has a 2D array of textfields, each of which are updating their text properly throughout the application. On each iteration of change, I change the text of the textfield then I make it's background green for half a second and turn it back to white. The issue is that, after the first iteration of the change, the textfields no longer flash green. When I comment out the portion that converts the background back to white, the rest works and the cells progressively turn green one by one (correctly), which indicates that it is working and executing properly. I tried to address this by repainting and revalidating the UI but it's not working. What is going on?

Below is my code that updates the UI.

    try {
        textfieldArray[row][col].repaint();
        textfieldArray[row][col].revalidate();
        textfieldArray[row][col].setBackground(Color.green);
        textfieldArray[row][col].repaint();
        textfieldArray[row][col].revalidate();
        Thread.sleep(300);
        textfieldArray[row][col].setBackground(Color.white);
        textfieldArray[row][col].repaint();
        textfieldArray[row][col].revalidate();
    } catch (InterruptedException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

Swing is a single threaded framework, it also NOT thread safe. This means two things.

First, you should never perform any long running or blocking operations within the context of the Event Dispatching Thread and...

Secondly, you should never update/modify the UI, or anything the UI depends on, from outside the context of the Event Dispatching Thread.

This means, your Thread.sleep is blocking the EDT, preventing from process paint requests.

Instead, you need some way you can trigger an update to occur after a specified delay. If that doesn't scream Swing Timer , I don't know what does

I would highly recommend taking the time to read through Concurrency in Swing for the background of why your code isn't working and possibly How to Use Swing Timers for a solution

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Test {

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

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private JTextField field;

        public TestPane() {
            setLayout(new GridBagLayout());
            field = new JTextField("All your bases beloging to us", 20);
            JButton blink = new JButton("Blink");
            Timer timer = new Timer(500, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    field.setForeground(null);
                    field.setBackground(null);
                }
            });
            timer.setRepeats(false);

            GridBagConstraints gbc = new GridBagConstraints();
            gbc.gridwidth = GridBagConstraints.REMAINDER;

            add(field, gbc);

            blink.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    field.setForeground(Color.WHITE);
                    field.setBackground(Color.GREEN);
                    timer.start();
                }
            });

            add(blink, gbc);
        }

    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM