问题
I want to be able to click the JButton and change the next individual ellipse I make to its respective color, Red or Black, from its default Blue. So far I'm able to change the color of all the ellipses I have made.
public class MainClient {
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MainClient window = new MainClient();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public MainClient() {
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final SpriteField panel = new SpriteField();
panel.setBounds(0, 110, 782, 331);
panel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int tX = e.getX();
int tY = e.getY();
panel.CreateObjectAt(tX,tY);
}
});
frame.getContentPane().setLayout(null);
panel.setBackground(Color.LIGHT_GRAY);
frame.getContentPane().add(panel);
final JButton btnRed = new JButton("black");
btnRed.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
panel.setColor(Color.BLACK);
}
});
btnRed.setBounds(229, 500, 97, 25);
frame.getContentPane().add(btnRed);
JButton btnRed_1 = new JButton("red");
btnRed_1.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
panel.setColor(Color.RED);
}
});
btnRed_1.setBounds(342, 500, 97, 25);
frame.getContentPane().add(btnRed_1);
}
}
I have a SriteField Class
public class SpriteField extends JPanel
{
ArrayList<RoundSprite>mSprites = new ArrayList<RoundSprite>();
private Color color = Color.BLUE;
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
AffineTransform tOldTransform = g2.getTransform();
for(RoundSprite tOne:mSprites)
{
tOne.DrawSprite(g2, color);
}
g2.setTransform(tOldTransform);
}
public void CreateObjectAt(int tX, int tY)
{
//make sprite
RoundSprite mLonely = new RoundSprite();
//set position
mLonely.SetPosition(tX, tY);
//add to array
mSprites.add(mLonely);
repaint();
}
public void setColor(Color color)
{
this.color = color;
repaint();
}
}
I have a RoundSprite Class
public class RoundSprite
{
int mX;
int mY;
private Color color;
void DrawSprite(Graphics2D g2, Color color)
{
AffineTransform tOldTransform = g2.getTransform();
g2.setColor(color);
g2.translate(mX, mY); //got it out from the corner
g2.draw(new Ellipse2D.Double(-15, -22, 30, 50));
g2.setTransform(tOldTransform);
}
public void SetPosition(int tX, int tY) //g2.translate
{
mX = tX;
mY = tY;
}
回答1:
There are three core issues...
One
In order for the panel_1
MouseListener
to change the color of the sprites within panel
, the MouseListener
requires a reference to the panel
.
You could declare the panel
as final
within the initialize
method, but I prefer to make the panel
a private
instance field of the MainClient
.
Two
In order to change the color, the SpriteField
needs to provide a means by which interested parties can request a change.
This is going to require SpriteField
to provide some kind of method that interested parties can call when they need to, for example, a setColor
method...
public class SpriteField extends JPanel {
private Color color = Color.BLACK;
//...
public void setColor(Color color) {
this.color = color;
repaint();
}
Then panel_1
's MouseListener
can now reference the SpriteField
and call a method which can produce a change...
panel_1.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
System.out.println("Click");
panel.setColor(Color.BLUE);
}
});
Three
You need some way to tell the sprite what color it should be...
This one depends on what it is you want to achieve...
If you want to paint ALL the sprites the same color, then you need some way to tell the sprites which color they should use, for example, you could change the DrawSprite
method to accept a Color
parameter...
public class RoundSprite {
//...
void DrawSprite(Graphics2D g2, Color color) {
And within the SpriteField
paintComponent
, pass the color to the sprite
public class SpriteField extends JPanel {
//...
private Color color = Color.BLACK;
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
AffineTransform tOldTransform = g2.getTransform();
for (RoundSprite tOne : mSprites) {
tOne.DrawSprite(g2, color);
}
g2.setTransform(tOldTransform);
}
Now, this will paint ALL the sprites within the field the same color, if you want to change the color of individual sprites, this comes infinitely more complicated...
Lets leave aside the issues of selecting a sprite for the moment...
Basically, you would need to apply the same principle from point Two to the RoundSprite
class.
You would need to supply a method that could set/get
the desired color. You would need to store this value in an instance field of the RoundSprite
class and when DrawSprite
is called, apply that Color
to the Graphics
context.
This would mean that SpriteField
won't need to perform any color management, beyond passing the request for change from a caller to the selected sprite, so it would still need a setColor
method...
Side Notes...
You might like to have a read through Code Conventions for the Java TM Programming Language, it will make it easier for people to read your code and for you to read others
Avoid using null
layouts, pixel perfect layouts are an illusion within modern ui design. There are too many factors which affect the individual size of components, none of which you can control. Swing was designed to work with layout managers at the core, discarding these will lead to no end of issues and problems that you will spend more and more time trying to rectify
Oh, and you realise that there already is a JButton
class that probably should be used instead of a JPanel
with a MouseListener
....?
来源:https://stackoverflow.com/questions/25110272/how-to-change-the-color-of-an-individual-ellipse-when-clicking-a-jbutton