-1

我是一名学生,在制作我的一个项目时遇到了麻烦,这只是我最终项目实际情况的一小部分,但我正试图尽可能地将它划分开来。

我遇到的具体问题与创建一个 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);
   }
}
4

1 回答 1

2

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

我尝试添加一些小的修改,但没有一个可以工作,我删除了它,以便在找到解决方案时给你更多的自由。

你从来没有提到什么是错的/你想要实现什么......除了上面和标题:选择对象,已经重新绘制

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

JFrame1)在所有组件都添加完之前不要设置可见(否则会出现内容不可见等问题)

2)不要调用setSizeJFrame不是覆盖getPreferredSize()JPanel返回Dimension适合对象上的图纸Graphics和/或使用适当的LayoutManager. 比我们可以调用pack()而不是setSize(...)on JFrame

3) Swing 组件应该通过块在Event Dispatch Thread上创建和操作。阅读 Swing 中的并发了解更多信息。SwingUtilities.invokeLater(Runnable r)

4)当你使用validate()它时,应该跟着一个调用repaint()来反映所做的更改。

5)您还使用了一个默认JFrame布局,BorderLayout您向其中添加了一个面板,并且默认情况下,球(使用按钮侦听器)BorderLayout将添加到其BorderLayout.CENTER上,因此每次调用JFrame#add(Component c)您都将旧/替换为JPanel另一个。

6)JPanel如果 2 Balls 最终处于重叠位置Ball,则它会像您一样使用,顶部JPanel将覆盖底部Ball......您需要一个透明面板,即JComponent#setOpaque(false).

7)当我做自定义绘画时,我很少使用JComponent或其扩展。我宁愿创建一个虚拟表示我需要绘制/显示的内容或其他内容(可能是个人喜好)Object。这些对象将在 my中可视化,它将调用它们的方法,将对象传递给每个对象,然后根据字段数据绘制自己。JPanel paintComponent(..)draw(..)GraphicsJPanelBall

这是我制作的一个简短示例(考虑到上述内容):

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

在此处输入图像描述

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;
    }
}
于 2013-02-16T17:25:24.863 回答