Plot points using paint(g) and run()

2019-09-19 02:45发布

问题:

What I want to do is once I pressed the button "GO", it will paint/draw 3 ovals with different coordinates. I've tried repainting but seems it doesn't work. It only shows one oval which is the last oval. I want it to stack up and append the ovals.

Here's my code:

import javax.swing.*; 
import java.awt.Graphics; 
import java.awt.*; 
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Test extends JFrame implements ActionListener{
JButton button;
int[] itoken;
int x,y;

public Test() {
super("Test");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(600,500);
this.setVisible(true);
this.setResizable(true);
this.setLayout(null);

button= new JButton("GO");
button.setBounds(500, 100, 50,50);

this.add(button);
button.addActionListener(this);
}

public void actionPerformed(ActionEvent e){ 
    if(e.getSource()==button){
        String text= "200 300 250 150 400 100";
        String[] token= text.split("\\W");
        itoken= new int[token.length];
        int i=0;
        for (String str : token){
            itoken[i++] = Integer.parseInt(str);
        }
        for(i=0; i<itoken.length; i++)
        System.out.println(itoken[i]);
    run();
    }
}

public void paint(Graphics g) {
    super.paint(g);
        g.drawOval(x - 5, y - 5, 10, 10);
}   

public void run(){
    int i=0;        
    while(i<itoken.length-1){
        repaint();
        x=itoken[i];
        y=itoken[i+1];
        i++;
    }
}

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

回答1:

Note - I was working on this answer right before you deleted your previous question, so the answer may see a little off in terms of the new code you posted in this question, but it gets you towards the same goal.

  1. Don't initialize everthing in the actionPerformed. You're getting a NullPointerException because paint is called by the frame implicitly before the array is initialized. What I did was create a method to initialize it

    int[] iToken = initArray();
    ...
    private int[] initArray() {
         String text = "200 300 250 150 400 100";
         String[] token = text.split("\\W");
         int[] itoken = new int[token.length];
         int i = 0;
    
         for (String str : token) {
             itoken[i++] = Integer.parseInt(str);
         }
    
         return itoken;
    }
    
  2. Don't paint on top level containers like JFrame. Instead us a JPanel or JCompoent and override paintComponent, and override getPreferredSize() in your JPanel so you won't have to set the size of your JFrame. Just pack() it.

  3. Run Swing apps from the Event Dispatch Thread like this

    public static void main(String[] args) {
        SwingUtilitiies.invokeLater(new Runnable(){
            public void run(){
                new Test();
            }
        });
    }
    
  4. You never add your button to the frame.

  5. Don't use a null layout. Use Layout Managers.

  6. Add you components, then call setVisible


Here's the running refactored code

import javax.swing.*;
import java.awt.Graphics;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Test extends JFrame implements ActionListener {

    JButton button;
    boolean paint = false;
    int x, y;
    int[] iToken = initArray();

    public Test() {

        super("Test");

        button = new JButton("GO");
        button.setBounds(500, 100, 50, 50);
        button.addActionListener(this);
        add(button, BorderLayout.SOUTH);
        add(new DrawPanel());

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.pack();
        this.setVisible(true);
        this.setResizable(true);

    }

    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == button) {
            paint = true;
            repaint();
        }
    }

    private int[] initArray() {
        String text = "200 300 250 150 400 100";
        String[] token = text.split("\\W");
        int[] itoken = new int[token.length];
        int i = 0;
        for (String str : token) {
            itoken[i++] = Integer.parseInt(str);
        }
        return itoken;
    }

    public class DrawPanel extends JPanel {

        public void paintComponent(Graphics g) {
            super.paintComponent(g);

            if (paint) {
                for (int i = 0; i < iToken.length; i += 2) {
                    x = iToken[i];
                    y = iToken[i + 1];
                    g.drawOval(x - 5, y - 5, 10, 10);
                }
            }
        }

        public Dimension getPreferredSize() {
            return new Dimension(500, 500);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Test();
            }
        });
    }
}