Java:选择已重新绘制的对象

时间:2013-02-16 15:35:23

标签: java swing jpanel paintcomponent

我是一名学生,并且正在做一个项目,这只是我的最终项目实际上的一点,但我试图尽可能地划分它。

我遇到的具体问题与创建一个java应用程序有关,该应用程序显示一个带有按钮的框架,允许用户在屏幕上创建多个球,然后您可以通过单击它们来选择每个球。

我尝试添加一些小修改,但是如果没有它们正在工作我将其删除,以便在找到解决方案时为您提供更多自由。

以下是Simulation类的代码:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Simulation {

   int noOfBallClicks = 0;

   Simulation() {
      buildTheGUI();
   }
   JFrame frame = new JFrame();
   JFrame frame2 = new JFrame();
   JPanel panal = new JPanel();
   JButton add = new JButton("add a new object");

   public void buildTheGUI() {
      frame.setVisible(true);
      frame.setSize(500, 500);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.add(panal);
      panal.add(add);
      add.addActionListener(new ButtonClickHandler());
   }

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

   class ButtonClickHandler implements ActionListener {

      public void actionPerformed(ActionEvent e) {
         noOfBallClicks = noOfBallClicks++;
         frame.add(new Ball());
         frame.validate();
      }
   }
}

以下是Ball类的代码:

import javax.swing.*;
import java.awt.*;
import java.util.Random;

public class Ball extends JPanel {

   private int x;
   private int y;
   private int w;
   private int h;

   Ball() {
      this.x = 200;
      this.y = 200;
      this.w = 100;
      this.h = 100;
   }

   Ball(int a) {
      Random rand = new Random();
      this.w = 100;
      this.h = 100;
      this.x = rand.nextInt(300);
      this.y = rand.nextInt(300);
   }

   public void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.setColor(Color.RED);
      g.fillOval(x, y, h, w);
   }
}

1 个答案:

答案 0 :(得分:2)

  

我遇到的具体问题与创建java应用程序有关   显示带有按钮的框架,允许用户创建   屏幕上有多个球,然后您可以选择每个球   点击它们。

     

我已经尝试添加小修改,但不使用它们   将其删除,以便在找到解决方案时为您提供更多自由。

你永远不会提到错误/想要实现的目标......除了以上和标题:选择已经重新绘制的对象

但是我在给出的代码中看到了一些问题:

1)在添加所有组件之前,不要将JFrame设置为可见(或者您将遇到内容不可见等问题)

2)不要在setSize上致电JFrame而是覆盖getPreferredSize()的{​​{1}},并返回符合JPanel对象上图纸的Dimension和/或使用适当的Graphics。我们可以在LayoutManager上拨打pack()而不是setSize(...)

3)应通过JFrame块在事件调度线程上创建和操作Swing组件。 Read Concurrency in Swing了解更多信息。

4)当您使用SwingUtilities.invokeLater(Runnable r)时,应该调用validate()来反映所做的更改。

5)您还使用了repaint()的默认JFrame布局添加了一个面板,而默认BorderLayout的球(使用按钮监听器)将添加到其中BorderLayout所以每次致电BorderLayout.CENTER时,您都会将旧的 / JFrame#add(Component c)替换为另一个。

6)正如使用JPanel一样,如果2 JPanel最终处于重叠位置,则顶部Ball及其Ball将覆盖底部JPanel {1}} ...您需要一个透明的面板,即Ball

7)当我进行自定义绘画时,我很少使用JComponent#setOpaque(false)或其扩展名。我宁愿创建一个JComponent,它将作为我需要绘制/显示的内容的虚拟表示或任何(可能是个人偏好)。这些对象将在我的Object JPanel中显示,而paintComponent(..)draw(..)方法将Graphics JPanel对象传递给每个Ball这将根据字段数据绘制自己。

这是我做的一个简短例子(考虑到上述情况):

所有绿色balls已被选中,即点击,而红色则没有。

enter image description here

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

public class Test {

    public Test() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        final DrawPanel drawPanel = new DrawPanel();

        drawPanel.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent me) {
                super.mouseClicked(me);
                for (Ball b : drawPanel.getBalls()) {//iterate through each ball
                    if (b.getBounds().contains(me.getPoint())) {//get the ball bounds and check if mouse click was within its bounds
                        if (!b.isSelected()) {//check if ball has been clicked on
                            b.setSelected(true);
                        } else {
                            b.setSelected(false);
                        }
                        drawPanel.repaint();//so ball color change will be shown
                    }
                }

            }
        });

        JPanel controlPanel = new JPanel();

        JButton createBallButton = new JButton("Add ball");
        createBallButton.addActionListener(new ActionListener() {
            Random rand = new Random();
            private int counter = 1;

            public void actionPerformed(ActionEvent e) {

                int ballRadius = 10;
                int x = rand.nextInt(drawPanel.getWidth());
                int y = rand.nextInt(drawPanel.getHeight());

                //check that we dont go offscreen by subtarcting its radius unless its x and y are not bigger than radius
                if (y > ballRadius) {
                    y -= ballRadius;
                }
                if (x > ballRadius) {
                    x -= ballRadius;
                }

                drawPanel.addBall(new Ball(x, y, ballRadius, counter));//add ball to panel to be drawn
                counter++;//increase the ball number
            }
        });

        final JTextArea jtf = new JTextArea(5, 10);
        jtf.setEditable(false);
        JButton printSelectedBallButton = new JButton("Print selected balls");
        printSelectedBallButton.addActionListener(new ActionListener() {
            Random rand = new Random();
            private int counter = 1;

            public void actionPerformed(ActionEvent e) {
                jtf.setText("");
                for (Ball b : drawPanel.getBalls()) {
                    if (b.isSelected()) {
                        jtf.append("Selected: " + b.getNumber() + "\n");
                    }
                }

            }
        });

        controlPanel.add(createBallButton);
        controlPanel.add(printSelectedBallButton);
        JScrollPane jsp = new JScrollPane(jtf);
        controlPanel.add(jsp);

        frame.add(drawPanel);
        frame.add(controlPanel, BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);

    }

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

class DrawPanel extends JPanel {

    ArrayList<Ball> balls = new ArrayList<>();

    public void addBall(Ball b) {
        balls.add(b);
        repaint();
    }

    public ArrayList<Ball> getBalls() {
        return balls;
    }

    @Override
    protected void paintComponent(Graphics grphcs) {
        super.paintComponent(grphcs);
        Graphics2D g2d = (Graphics2D) grphcs;
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        for (Ball ball : balls) {
            ball.draw(g2d);
        }
    }

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

class Ball {

    private Color color;
    private int x, y;
    private int radius;
    private final int number;
    private boolean selected;

    Ball(int x, int y, int radius, int counter) {
        this.x = x;
        this.y = y;
        this.radius = radius;
        this.number = counter;
        selected = false;
        this.color = Color.RED;//default color of unselected ball
    }

    public void draw(Graphics2D g2d) {
        Color prevColor = g2d.getColor();
        g2d.drawString(number + "", x + radius, y + radius);//draw the number of ball
        g2d.setColor(color);
        g2d.fillOval(x, y, radius, radius);
        g2d.setColor(prevColor);
    }

    public Rectangle2D getBounds() {
        return new Rectangle2D.Double(x, y, radius, radius);
    }

    public void setSelected(boolean selected) {
        this.selected = selected;
        if (selected) {
            color = Color.GREEN;
        } else {
            color = Color.RED;
        }
    }

    boolean isSelected() {
        return selected;
    }

    int getNumber() {
        return number;
    }
}