Java:选择已重新粉刷的对象 [英] Java: selecting objects, that have been repainted

查看:249
本文介绍了Java:选择已重新粉刷的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是一名学生,正在做我的一个项目,这只是我最终项目的实际情况的一点点,但我正在尝试将其尽可能地划分.

I am a student and having trubble making one of my projects this is only one bit of what my final project will actual be like but i am trying to compartmentalize it as much as possible.

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

the specific problem I have is related to creating a java application that displays a frame with a button allowing the user to create multiple balls on screen and then have you be able to select each one by clicking on them.

我尝试添加一些小的修改,但是由于没有任何修改,我将其删除了,以便在寻找解决方案时为您提供更多的自由.

I have tryed to add small modifications but with non of them working i removed it so that it gives you more freedom when finding a solution.

这是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);
   }
}

推荐答案

我遇到的特定问题与创建Java应用程序有关 显示带有按钮的框架,允许用户创建 屏幕上有多个球,然后您是否可以选择每个球 通过点击它们.

the specific problem I have is related to creating a java application that displays a frame with a button allowing the user to create multiple balls on screen and then have you be able to select each one by clicking on them.

我尝试添加一些小的修改,但没有一个修改我 删除它,以便在寻找解决方案时为您提供更多的自由.

I have tryed to add small modifications but with non of them working i removed it so that it gives you more freedom when finding a solution.

您永远不会提及出什么问题/想要实现的目标...除了上面的内容和标题:选择已重新粉刷的对象

You never mention what is wrong/what you want to achieve... Besides the above and title: selecting objects, that have been repainted

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

However I see a few problems in the code given:

1)在添加所有组件之前,不要将JFrame设置为可见(否则您将遇到诸如内容不可见的问题)

1) Dont set JFrame visible until all components have been added (or you will have problems such as content not being visible)

2)不要在JFrame上调用setSize,而应覆盖JPanelgetPreferredSize()并返回与Graphics对象上的图形相匹配的Dimension和/或使用适当的LayoutManager.比我们可以在JFrame上调用pack()代替setSize(...).

2) Dont call setSize on JFrame rather override getPreferredSize() of JPanel and return Dimensions which fit the drawings on Graphics object and/or use an appropriate LayoutManager. Than we can call pack() instead of setSize(...) on JFrame.

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

3) Swing components should be created and manipulated on Event Dispatch Thread via SwingUtilities.invokeLater(Runnable r) block. Read Concurrency in Swing for more.

4)使用validate()时,应先调用repaint()以反映所做的更改.

4) When you use validate() it should be followed by a call to repaint() to reflect changes made.

5)您还使用了默认的JFrame布局BorderLayout,并向其中添加了面板,然后默认情况下,BorderLayout的球(使用按钮侦听器)将添加到其BorderLayout.CENTER中,因此每个呼叫JFrame#add(Component c),您正在用另一个替换旧的 ball /JPanel.

5) You are also using a default JFrame Layout of BorderLayout to which you add a panel, and than balls (using the button listener) by default BorderLayout will add to its BorderLayout.CENTER so on each call to JFrame#add(Component c) you are replacing the old ball/JPanel with another.

6)如果使用JPanel时,就像2个Ball的最终重叠位置一样,顶部Ball及其JPanel将覆盖底部Ball....透明面板,即JComponent#setOpaque(false).

6) As it stands using JPanel like you have if 2 Balls end up in an overlapping position the top Ball and its JPanel will cover the bottom Ball... You need a transparent panel i.e JComponent#setOpaque(false).

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

7) When I do custom painting, I rarely use JComponent or its extensions. I rather create an Object which will act as virtual representation of what I need to be drawn/displayed or whatever (maybe personal preference). These objects will than be visualized in my JPanel paintComponent(..) which will call their draw(..) method passing the Graphics object of the JPanel to each Ball which will than draw itself according to the the fields data.

这是我做的一个简短示例(牢记以上内容):

Here is a short example I made (with the above in mind):

所有绿色balls已被选中,即被点击,而红色尚未被选中.

All green balls have been selected i.e clicked on, while the red has not.

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;
    }
}

这篇关于Java:选择已重新粉刷的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆