问题描述
我是一名学生,正在做我的一个项目,这只是我最终项目的实际情况的一点点,但我正在尝试将其尽可能地划分.
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);
}
}
推荐答案
我尝试添加一些小的修改,但没有一个修改我 删除它,以便在寻找解决方案时为您提供更多的自由.
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
,而应覆盖JPanel
的getPreferredSize()
并返回与Graphics
对象上的图形相匹配的Dimension
和/或使用适当的LayoutManager
.比我们可以在JFrame
上调用pack()
代替setSize(...)
.
2) Dont call setSize
on JFrame
rather override getPreferredSize()
of JPanel
and return Dimension
s 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 Ball
s 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(..)
方法,将JPanel
的Graphics
对象传递给每个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:选择已重新粉刷的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!