1

Here is my Code:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

public class Main {
// code main
public static void main(String[] args) {
    JFrame frame = new JFrame();
    frame.setSize(460, 500);
    frame.setTitle("Circles generator");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            frame.setVisible(true);

        }

    });

    String input = JOptionPane.showInputDialog("Enter n:");
    CustomComponents0 component = new CustomComponents0();
    frame.add(component);
    frame.getContentPane().validate();
        System.out.println("work before");
    frame.getContentPane().repaint();
        System.out.println("work");

    frame.getContentPane().repaint();
        System.out.println("work after");

}

// why is not JComponent
static class CustomComponents0 extends JLabel {

    private static final long serialVersionUID = 1L;

    @Override
    public Dimension getMinimumSize() {
        return new Dimension(200, 100);

    }

    @Override
    public Dimension getPreferredSize() {
        return new Dimension(300, 200);

    }

    @Override
    public void paintComponent(Graphics g) {
        System.out.println("paint");
        int margin = 10;
        Dimension dim = getSize();
        super.paintComponent(g);
        g.setColor(Color.red);
        g.fillRect(margin, margin, dim.width - margin * 2, dim.height - margin * 2);

    }

}

here is the code and I want run repaint before work and run repaint after work. When I run it, it should print

work before
paint
work
paint
work after

but there are only one paint and it's after work, Why is that happen? How can I fix that?

Thanks.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Boyuan Wang
  • 57
  • 11
  • 2
    Why? What needs fixing? Why worry about precisely when and if a painting occurs? Understand that you can only request a painting not require it (for the most part). – Hovercraft Full Of Eels May 26 '17 at 20:37
  • 3
    That is not the way painting works. A "repaint()" is just a request to paint a component. When you have two requests in a row, they are consolidated into a single request. What is the point of this logic? If you need a time lapse between painting then you can use a `Swing Timer`. Read the section from the Swing tutorial on [How to Use Swing Timers](http://docs.oracle.com/javase/tutorial/uiswing/misc/timer.html). – camickr May 26 '17 at 20:39

1 Answers1

1

You must construct and manipulate Swing GUI objects only on the event dispatch thread. Because your program is incorrectly synchronized, any result is possible. It will depend in part on how far the initial thread gets before starting the EventQueue. Moreover, println() itself may be synchronized, and "events being posted to the EventQueue can be coalesced."

The variation below reliably shows the following output because events are dispatched "In the same order as they are enqueued." Note in particular how the calls to repaint() are coalesced. While this approach is illustrative, it is needlessly cumbersome for your likely goal. Instead, use javax.swing.Timer to pace animation as shown here.

Console:

paint
work before
work
work after
paint

Code:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JLabel;

/** @see https://stackoverflow.com/a/44212328/230513 */
public class Main {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            JFrame frame = new JFrame();
            frame.setTitle("Circles generator");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            CustomComponent component = new CustomComponent();
            frame.add(component);
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
            EventQueue.invokeLater(() -> { System.out.println("work before"); });
            EventQueue.invokeLater(() -> { frame.repaint(); });
            EventQueue.invokeLater(() -> { System.out.println("work"); });
            EventQueue.invokeLater(() -> { frame.repaint(); });
            EventQueue.invokeLater(() -> { System.out.println("work after"); });
        });
    }

    static class CustomComponent extends JLabel {

        private static final int N = 10;

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 200);
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            System.out.println("paint");
            g.setColor(Color.red);
            g.fillRect(N, N, getWidth() - N * 2, getHeight() - N * 2);
        }
    }
}
trashgod
  • 203,806
  • 29
  • 246
  • 1,045