Drawing rectangle within the loop?

老子叫甜甜 提交于 2020-12-15 06:38:30

问题


I'm trying to animate a rectangle based on a coordinate determined by for-loop, inside a button. Here is my JComponent Class:

public class Rect extends JComponent {
    public int x;
    public int y;
    public int w;
    public int h;
    
    public Rect (int x, int y, int w, int h) {
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        repaint();
    }

    @Override
    public void paintComponent(Graphics g)  {
        Graphics2D g2 = (Graphics2D) g;
        super.paintComponent(g);
        g2.setColor(Color.green);
        g2.drawRect(x+15, y+15, w, h);
    }
}

and here is my button and button inside JFrame class:

public class MainFrame extends JFrame {
    Rect R = new Rect(15, 15, 50, 50);
    JPanel lm = new JPanel();
    LayoutManager lay = new OverlayLayout(lm);
    JButton animate = new JButton("animate");

    public MainFrame () {
        setSize(1200, 700);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        lm.setLayout(lay);
        lm.add(R);
}
    animate.addActionListener(new ActionListener() {
           public void actionPerformed(ActionEvent e) { 
               for (int k = 0; k < 500; k+=50) {
                R = new Rect(k, k, 50, 50);
               validate();
               repaint();
               }
           }   
  });
}

But when I run the code and click the button, nothing happens. What's wrong?

EDIT: I run the frame inside my main class like this:

public class OrImage {
    public static void main(String[] args) throws Exception
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                MainFrame mf = new MainFrame();
                mf.setVisible(true);
            }
        });   
    }
}

回答1:


I changed the code of class MainFrame such that when you press the animate button, something happens, but I don't know if that is what you want to happen.

I did not change class Rect and I added main() method to MainFrame just to keep everything in one class.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.LayoutManager;
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.OverlayLayout;

public class MainFrame extends JFrame {
    Rect R = new Rect(15, 15, 50, 50);
    JPanel lm = new JPanel();
    LayoutManager lay = new OverlayLayout(lm);
    JButton animate = new JButton("animate");

    public MainFrame () {
        setSize(1200, 700);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        lm.setLayout(lay);
        lm.add(R);
        animate.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) { 
                for (int k = 0; k < 500; k+=50) {
                    R = new Rect(k, k, 50, 50);
                    lm.add(R);
                }
                lm.revalidate();
                lm.repaint();
            }   
        });
        add(lm, BorderLayout.CENTER);
        add(animate, BorderLayout.PAGE_END);
        setLocationByPlatform(true);
        setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new MainFrame());
    }
}

The main change is in method actionPerformed(). You need to add R to the JPanel. You need to call revalidate() on the JPanel because you have changed the number of components that it contains. And after calling revalidate() you should call repaint() (again, on the JPanel) to make it redraw itself.

This is how it looks before pressing animate.

And this is how it looks after pressing animate

EDIT

As requested – with animation.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.LayoutManager;
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.OverlayLayout;
import javax.swing.Timer;

public class MainFrame extends JFrame {
    Rect R = new Rect(15, 15, 50, 50);
    JPanel lm = new JPanel();
    LayoutManager lay = new OverlayLayout(lm);
    JButton animate = new JButton("animate");
    private int  x;
    private int  y;
    private Timer  timer;

    public MainFrame () {
        setSize(1200, 700);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        lm.setLayout(lay);
        lm.add(R);
        timer = new Timer(500, event -> {
            if (x < 500) {
                lm.remove(R);
                x += 50;
                y += 50;
                R = new Rect(x, y, 50, 50);
                lm.add(R);
                lm.revalidate();
                lm.repaint();
            }
            else {
                timer.stop();
            }
        });
        timer.setInitialDelay(0);
        animate.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                timer.start();
            }   
        });
        add(lm, BorderLayout.CENTER);
        add(animate, BorderLayout.PAGE_END);
        setLocationByPlatform(true);
        setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new MainFrame());
    }
}


来源:https://stackoverflow.com/questions/64925307/drawing-rectangle-within-the-loop

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!