I am writing a program, and the mouse listener, mousePressed(), does not seem to respond. I have written a few GUI programs now, and having compared this code, I do not see any significant difference that would explain the lack of mouse listening. The following code is incomplete and has portions that are meant for testing functionality only, and some of it may not make sense. I just need to know why mousePressed() is not working.
/**This class creates a panel that draws a polygon with as many vertices as the user desires. It will have a button that tells the component to close the
polygon. Vertices are chosen with clicks of the mouse on the drawing surface.*/
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class PolygonDraw extends JPanel implements ActionListener{
DrawPanel drawingSurface;
int[][] coordinates, oldCoordinates;
int indices = 1;
static int x = 50;
public PolygonDraw(){
//create painting panel.
setLayout(new BorderLayout());
drawingSurface = new DrawPanel();
add(drawingSurface, BorderLayout.CENTER);
JButton closePoly = new JButton("Close the Polygon");
closePoly.addActionListener(this);
JButton clear = new JButton("Clear");
clear.addActionListener(this);
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new GridLayout(0,1));
buttonPanel.setBorder(BorderFactory.createEtchedBorder());
buttonPanel.add(clear);
buttonPanel.add(closePoly);
add(buttonPanel, BorderLayout.SOUTH);
}
private class DrawPanel extends JPanel{
public void DrawPanel(){
addMouseListener(new MouseAdapter(){
/**
This creates an array containing coordinates for every mouse press. Logic in this allows for the creation of array that get larger and larger as more
vertices are created by the user.
*/
public void mousePressed(MouseEvent evt){//compile list of vertices
//create the last element in the array.
//create an array with i elements
/*coordinates = new int[indices][2];
coordinates[indices - 1][0] = evt.getX();
coordinates[indices - 1][1] = evt.getY();
if (oldCoordinates != null){
for (int i = 0; i < indices - 1; i++){
coordinates[i][0] = oldCoordinates[i][0];
coordinates[i][1] = oldCoordinates[i][1];
}
}
oldCoordinates = coordinates;
indices++;*/
x += 5;
repaint();
}
});
}
public void paintComponent(Graphics g){//draw lines between vertices, finish polygon, and fill polygon in with a color.
//int x, y;
//super.paintComponent(g);
/*g.setColor(Color.BLACK);
for(int i = 0; i <= indices; i++){
x = coordinates[i][0];
y = coordinates[i][1];
g.fillOval(x + 2, y + 2, 4, 4);
}
*/
g.fillRect(x,50,50,50);
}
}
public void actionPerformed(ActionEvent evt){//Clear drawing area, or close vertices to make polygon.
}
}
public void DrawPanel() { is not a valid constructor, it's just a normal method.
You should be using something more like public DrawPanel() {, this way the MouseListener will be registered when you create a new instance of the class
Also, make sure you're calling super.paintComponent, otherwise you will end up with a bunch of other issues...
#Override
protected void paintComponent(Graphics g) {//draw lines between vertices, finish polygon, and fill polygon in with a color.
super.paintComponent(g);
Related
I am trying to build a bounce game in Java. My project has three classes ie the Main class which creates a new window(frame) where the game buttons and bounce objects are drawn.
The GameInterface class which represents the properties of the frame being drawn and the RightPanel class which I created so that I could override the paint(Graphics) method to draw my bounce object. So far this is what I have managed to draw with the code.
You can see that I have two JPanels, one that holds my buttons and the other one that accepts the drawing of a round ball on it ie RightPanel
I need help with the Button Event listeners to move the ball up and down and when user holds the button down, it needs to keep moving down until reaches the down order, sam for the up button.
The code am using is provided below.
GameInterface class
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
public class GameInterface extends JFrame {
//we need this panel declaration in the class level for reference from other methods
RightPanel rightpanel;
//define the physical properties of the window
public GameInterface(){
setSize(new Dimension(600, 600));
setResizable(false);
setTitle("Bounce Game");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBackground(Color.black);
//define a new JSplitPane and use it to add two JPanels
JPanel leftpanel= new JPanel();
//add buttons to the left panel programatically
JButton up= new JButton("Move up");
//set the event listeners for the buttons
up.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
//move my ball up
//clear and redraw the ball while in a new position, use a timer or
something
}
});
JButton down = new JButton("Move down");
down.addActionListener(new AbstractAction() {
#Override
public void actionPerformed(ActionEvent e) {
//move my ball down
// rightpanel.getGraphics.fillColor(Color.RED);
}
});
leftpanel.add(up);
leftpanel.add(down);
//add a new RightPanel with a drawn red object
rightpanel= new RightPanel();
JSplitPane splitpane= new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftpanel,rightpanel);
this.add(splitpane);
setVisible(true);
}
}
RightPanel class
import javax.swing.*;
import java.awt.*;
public class RightPanel extends JPanel {
//define the position where the circle will be drawn
private int positionX=150;
private int positionY=150;
//I had an idea where we need a timer and then on delay we
//decrement positionX by 3 for move down but can't figure out how to clear RightPanel
private int radius=100;//as the shape is a circle
//override the paint method to draw the bounce ball on the second panel
#Override
public void paint(Graphics g) {
g.setColor(Color.RED);
g.fillOval(positionX,positionY,radius,radius);
}
}
Main class
public class Main
{
public static void main(String args[]){
new GameInterface();
}
}
How do I add logic to my code to make it move the circle up an down, Thank You.
I tried using a timer object to clear the panel and then redraw the ball in the new position of the ball but it draws a vertical bar, not clearing the original ball drawn.
Never call getGraphics() on a component.
Override paintComponent not paint
Call the super.paintComponent(g) in your override.
Give the RightPanel class setter methods that allow you to change the positionX and positionY locations for drawing,
In the button listener, call an appropriate setter method, and then call repaint() on on the RightPanel instance after changing the positions.
For example:
The key code below is here in the ActionListener where you update the position values and call repaint:
moveRightBtn.addActionListener(e -> {
// get and update the x position
int x = drawOval.getPositionX();
x += DELTA;
// call the setter method
drawOval.setPositionX(x);
// request that Java repaint the JPanel
drawOval.repaint();
});
and in the drawing JPanel's paintComponent method where you call the super's method and draw the oval:
#Override
protected void paintComponent(Graphics g) {
// this is needed to do house-keeping painting, to clear "dirty" pixels
super.paintComponent(g);
// this is needed to draw smooth graphics
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(OVAL_COLOR);
g2.fillOval(positionX, positionY, RADIUS, RADIUS);
}
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 javax.swing.*;
#SuppressWarnings("serial")
public class MoveCircle extends JPanel {
private static final int DELTA = 5;
private DrawOval drawOval = new DrawOval();
public MoveCircle() {
JButton moveRightBtn = new JButton("Move Right");
moveRightBtn.addActionListener(e -> {
// get and update the x position
int x = drawOval.getPositionX();
x += DELTA;
// call the setter method
drawOval.setPositionX(x);
// request that Java repaint the JPanel
drawOval.repaint();
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(moveRightBtn);
setLayout(new BorderLayout());
add(drawOval);
add(buttonPanel, BorderLayout.LINE_START);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
MoveCircle mainPanel = new MoveCircle();
JFrame frame = new JFrame("GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}
#SuppressWarnings("serial")
class DrawOval extends JPanel {
private static final int RADIUS = 100;
private static final int PANEL_WIDTH = 600;
private static final int PANEL_HEIGHT = 450;
private static final Color OVAL_COLOR = Color.RED;
private int positionX = 0;
private int positionY = 0;
public DrawOval() {
setPreferredSize(new Dimension(PANEL_WIDTH, PANEL_HEIGHT));
}
public int getPositionX() {
return positionX;
}
public void setPositionX(int positionX) {
this.positionX = positionX;
}
public int getPositionY() {
return positionY;
}
public void setPositionY(int positionY) {
this.positionY = positionY;
}
#Override
protected void paintComponent(Graphics g) {
// this is needed to do house-keeping painting, to clear "dirty" pixels
super.paintComponent(g);
// this is needed to draw smooth graphics
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(OVAL_COLOR);
g2.fillOval(positionX, positionY, RADIUS, RADIUS);
}
}
I'm trying to let a user draw a rectangle with their mouse.
I'm having two problems which I think may be related. Firstly, the third class I posted here, Colors.java, needs to use the same rectangle object from the mouse listener, which is the second class I provided (Mouse.java).
I tried to use getters and setters with this, when I went through the program in debug mode it had the correct rectangle object in the color() method, but once it went to paintComponent() I now have a null rectangle object. I don't know why this is.
Another problem I've been having is that the repaint() method does not always call the paintComponent() method. I think this could be because of the rectangle object being null but I'm not sure.
I tried to shorten up the code and replaced some code with comments. I also didn't think including the rectangle class was necessary since most of the class is filled with other functions totally unrelated to the this problem.
Any help to lead me in the right direction would be appreciated, I'm pretty stuck right now. Thanks!
public class JavaSwing extends JFrame implements ItemListener {
//Checkbox objects here
Colors colors = new Colors();
public void createGui() {
intersection = new JCheckBox("Draw Intersections");
intersection.setMnemonic(KeyEvent.VK_C);
intersection.setSelected(false);
//checkbox objects assigned like above
//checkbox listeners
JFrame frame = new JFrame("Rectangles");
frame.setSize(600, 600);
frame.setVisible(true);
Mouse mouse = new Mouse();
colors.setLayout(new BoxLayout(colors, BoxLayout.PAGE_AXIS));
colors.addMouseListener(mouse);
colors.addMouseMotionListener(mouse);
colors.add(Box.createRigidArea(new Dimension(0, 5)));
colors.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
JButton button = new JButton("Clear Image");
JPanel panel = new JPanel();
panel.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
panel.setBorder(BorderFactory.createLineBorder(Color.BLACK, 2));
panel.add(Box.createHorizontalGlue());
panel.add(intersection);
panel.add(Box.createRigidArea(new Dimension(10, 0)));
panel.add(union);
panel.add(Box.createRigidArea(new Dimension(10, 0)));
panel.add(commonArea);
panel.add(Box.createRigidArea(new Dimension(10, 0)));
panel.add(button);
frame.add(colors, BorderLayout.CENTER);
frame.add(panel, BorderLayout.PAGE_END);
}
#Override
public void itemStateChanged(ItemEvent e) {
//for checkboxes
}
public static void main(String args[]) {
JavaSwing javaSwing = new JavaSwing();
javaSwing.createGui();
}
}
Second Class:
public class Mouse extends MouseInputAdapter implements MouseListener{
Rectangle rectangleOne = new Rectangle(0, 0, 0, 0);
Colors colors = new Colors();
public void mousePressed(MouseEvent e) {
rectangleOne.setX(e.getX());
rectangleOne.setY(e.getY());
rectangleToDraw = new Rectangle(rectangleOne.getX(), rectangleOne.getY(),
rectangleOne.getWidth(), rectangleOne.getHeight());
colors.setRectangle(rectangleToDraw);
colors.color();
}
public void mouseReleased(MouseEvent e) {
int x2 = e.getX();
int y2 = e.getY();
rectangleOne.setWidth(x2 - rectangleOne.getX());
rectangleOne.setHeight(y2 - rectangleOne.getY());
rectangleToDraw = new Rectangle(rectangleOne.getX(), rectangleOne.getY(),
rectangleOne.getWidth(), rectangleOne.getHeight());
colors.setRectangle(rectangleToDraw);
colors.color();
}
Third Class:
public class Colors extends JPanel {
Rectangle rectangle;
public void setRectangle(Rectangle rectangle)
{
this.rectangle = rectangle;
}
public Rectangle getRectangle() {
return rectangle;
}
public void color() {
repaint();
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
if (getRectangle() != null) {
g.fillRect(getRectangle().getX(), getRectangle().getY(), getRectangle().getWidth(), getRectangle().getHeight());
}
}
}
The reason rectangle is null when you reach paintComponent is because the colors in Mouse is not the same as the colors in JavaSwing. In both classes you do Colors colors = new Colors(). That means you have two separate, unrelated, instances of the class. That's also the reason you aren't seeing a repaint happen when you call repaint() - you're calling it on a component that's not part of the actual component hierarchy being displayed.
If you change things so that you use the same Colors instance in both cases, it will work correctly. So change your Mouse code to this:
public class Mouse extends MouseInputAdapter implements MouseListener{
Rectangle rectangleOne = new Rectangle(0, 0, 0, 0);
Colors colors;
public Mouse(Colors colors){
this.colors = colors;
}
/* The rest of your methods here */
}
And then create your Mouse instance like this:
Mouse mouse = new Mouse(colors);
Also, although I don't think this is what you're talking about, I think I should mention that repaint() does not always result in paintComponent being called, even when you do it on the correct object. What it does is make a request that the component be repainted when the Event Dispatch Thread is next able to. Usually it will cause paintComponent to be called, but not always (for example if the component isn't visible, or if you call it multiple times before it can be repainted, which will result in it only being painted once).
I have 2 buttons, a reset button and a calculate button.
The only purpose of the reset button is to repaint a JPanel called p1.
The purpose of the calculate button is to make a calculation and update a JLabel.
The issue is that when the reset button is pressed, followed by the calculate button, the JPanel is repainted and it should not be (see code below where the repaint method is not present in the ActionListener() for calculateButton).
I am wondering why this is happening, and what I can do to stop the JPanel from being repainted when this button is pressed (the reset button's functions exactly as expected, by repainting the panel).
public class DrawCircles extends JFrame {
//the following are x and y locations of the centers of the circles
int center1X;
int center1Y;
int center2X;
int center2Y;
int center3X;
int center3Y;
public DrawCircles(){
final CircleDraw c = new CircleDraw(); //create a circledraw object to get the area of the triangle between them
final JPanel p1 = new JPanel(); //first panel to hold all other panels making the layout
JPanel buttonPanel = new JPanel();
p1.setLayout(new BorderLayout()); //set the layout of the panel to a border layout
JButton areaTriangle = new JButton("Calculate area of triangle");
JButton perimeterTriangle = new JButton("Calculate perimeter of triangle");
JButton reset = new JButton("Reset");
buttonPanel.setLayout(new BoxLayout(buttonPanel,0));
buttonPanel.add(areaTriangle);
buttonPanel.add(Box.createRigidArea(new Dimension(15,0)));
buttonPanel.add(perimeterTriangle);
buttonPanel.add(Box.createRigidArea(new Dimension(15,0)));
buttonPanel.add(reset); //add a button that says reset
reset.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
p1.repaint(); //redraw the circles and triangle
areaLabel.setText(""); //clear the label
}
});
calculateButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
areaLabel.setText("Area is "+ String.valueOf(2.0*c.getArea()));
}
});
resetButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent event) {
areaLabel.setText("");
}
});
add(p1);
}
public class CircleDraw extends JPanel {
int radius;
double s;
double area;
public CircleDraw(){
}
#Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Random rand = new Random(System.currentTimeMillis());
center1X=rand.nextInt(507);
center1Y=rand.nextInt(320);
center2X=rand.nextInt(507);
center2Y=rand.nextInt(320);
center3X=rand.nextInt(507);
center3Y=rand.nextInt(320);
//draw the 3 circles
g.drawOval(center1X, center1Y, 100,100);
g.drawOval(center2X, center2Y,100,100);
g.drawOval(center3X, center3Y, 100, 100);
//connect the centers of the circles with lines
g.drawLine(center1X+50, center1Y+50, center2X+50, center2Y+50);
g.drawLine(center2X+50, center2Y+50, center3X+50, center3Y+50);
g.drawLine(center3X+50, center3Y+50, center1X+50, center1Y+50);
}
}
public static void main(String[] args) {
DrawCircles frame = new DrawCircles();
frame.setSize(700,500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
You state:
The issue is that when the reset button is pressed, followed by the calculate button the panel is repainted and it should not be. (See code below where the repaint method is not present in the ActionListener() for calculateButton). I am wondering why this is happening, and what I can do to stop the panel from being repainted when this button is pressed. (The reset button functions exactly as expected, by repainting the panel).
It is impossible to guess what could be wrong based on the code you've posted so far. I urge you to consider creating and posting a minimal example program that allows us to see your problem for ourselves.
But having said that, I will add that you never have full control over when a component is painted or not, since many paintings are driven by the JVM responding to the operating system. This is one reason that program logic should never reside within a paint(Graphics g) or paintComponent(Graphics g) method override.
So your problem is really an XY Problem in disguise. You ask how to control the repainting of a component when you should instead be asking how to get your program logic out of one of the painting methods, and in fact this is my guess at the solution to your problem -- make sure that your painting method is used solely for painting and nothing else.
Edit
Yep, you have program logic within the paintComponent method, specifically this code:
Random rand = new Random(System.currentTimeMillis());
center1X=rand.nextInt(507);
center1Y=rand.nextInt(320);
center2X=rand.nextInt(507);
center2Y=rand.nextInt(320);
center3X=rand.nextInt(507);
center3Y=rand.nextInt(320);
Get it out of paintComponent and in its own method that will allow you to control when it is called.
Edit 2
For example, you could do this:
public class CircleDraw extends JPanel {
private int radius;
private double s;
private double area;
private Random rand = new Random(); // make this a field
// call this when you want to change the random images
public void randomizeDrawing() {
center1X = rand.nextInt(507);
center1Y = rand.nextInt(320);
center2X = rand.nextInt(507);
center2Y = rand.nextInt(320);
center3X = rand.nextInt(507);
center3Y = rand.nextInt(320);
repaint();
}
// and only do painting in paintComponent
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// draw the 3 circles
g.drawOval(center1X, center1Y, 100, 100);
g.drawOval(center2X, center2Y, 100, 100);
g.drawOval(center3X, center3Y, 100, 100);
// connect the centers of the circles with lines
g.drawLine(center1X + 50, center1Y + 50, center2X + 50, center2Y + 50);
g.drawLine(center2X + 50, center2Y + 50, center3X + 50, center3Y + 50);
g.drawLine(center3X + 50, center3Y + 50, center1X + 50, center1Y + 50);
}
I'm making a chess game, and I'm using a chessboard that I made with paint at 480x480, and got the pieces from some sprite and made each one of them 60x60 and transparent background. I managed to put the chessboard and the pieces on screen, but the positions are messy. I'm using null layout. I did:
chessBoardLabel.setBounds(0, 0+25, 480, 480);
the +25 is because of the Frame's thing that is on top and looks like it is considered in positioning.
as for the piece, for example:
for (int i = 0; i <= 7; i++)
whitePawnArray[i] = new whitePawnPiece(i*60,420+25);
the parameters set the xPos and yPos. For the bounds function, I did:
whitePawnLabel.setBounds(this.xPos, this.yPos, this.xPos+60, this.yPos+60);
But this happens:
If I do that:
for (int i = 0; i <= 7; i++)
whitePawnArray[i] = new whitePawnPiece(i*40,280+15);
this happens:
First: what happened to the positioning? Why doesn't it follow what I intended it to be?
Second: what is the 8th piece doing in the middle of nowhere?
package chess.game;
import java.util.*;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class chessMain extends JFrame{
public static void main (String arguments[]){
//Create White
whitePiece white_piece = new whitePiece();
whitePawnPiece[] whitePawnArray = new whitePawnPiece[8];
for (int i = 0; i <= 7; i++) whitePawnArray[i] = new whitePawnPiece(i*40,280+15);
/*whiteTowerPiece[] whiteTowerArray = new whiteTowerPiece[2];
whiteTowerArray[0] = new whiteTowerPiece(0,420);
whiteTowerArray[1] = new whiteTowerPiece(420,420);
whiteHorsePiece[] whiteHorseArray = new whiteHorsePiece[2];
whiteBishopPiece[] whiteBishopArray = new whiteBishopPiece[2];
whiteKingPiece whiteKing = new whiteKingPiece();
whiteQueenPiece whiteQueen = new whiteQueenPiece();*/
//Create Black
JFrame frame = new JFrame();
JPanel panel;
//Initialize
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("Chess");
frame.setSize (640,640);
frame.setResizable(false);
frame.setLayout(null);
panel = new JPanel();
panel.setLayout(null);
frame.getContentPane().add(panel);
//draw chessBoard
ImageIcon chessBoardIcon = new ImageIcon(frame.getClass().getResource("/chess/art/Chess_Art/chessBoard.png"));
JLabel chessBoardLabel = new JLabel(chessBoardIcon);
panel.add(chessBoardLabel);
chessBoardLabel.setBounds(0, 0+25, 480, 480);
frame.setComponentZOrder(chessBoardLabel, 1);
frame.setComponentZOrder(panel, 2);
//draw Pawn
for (int i = 0; i<=7; i++){
panel.add(whitePawnArray[i].whitePawnLabel);
whitePawnArray[i].draw();
frame.setComponentZOrder(whitePawnArray[i].whitePawnLabel, 0);
}
frame.setVisible(true);
}
}
public class whitePawnPiece extends whitePiece{
JLabel whitePawnLabel;
ImageIcon whitePawnIcon;
public whitePawnPiece(int x, int y){
whitePawnIcon = new ImageIcon(getClass().getResource("/chess/art/Chess_Art/white/whitePawnPiece.png"));
whitePawnLabel = new JLabel (whitePawnIcon);
//whitePawnLabel.setOpaque(true);
this.xPos = x;
this.yPos = y;
//this.draw();
}
#Override
public void move(int newX, int newY){
this.xPos = (newX/60)*60; //calcular nova pos
this.yPos = (newY/60)*60;
this.draw();
}
/*public void possibleMoves(){
selectorMark.drawNew(this.xPos, this.yPos);
selectorMark.drawNew(this.xPos - 60, this.yPos - 60);
if (this.yPos == 420) selectorMark.drawNew(this.xPos - 120, this.yPos - 120);
}*/
#Override
public void draw(){
//whitePawnIcon.paintIcon(null, chessGUI2.getGraphics(), xPos, xPos);
whitePawnLabel.setBounds(this.xPos, this.yPos, this.xPos+60, this.yPos+60); //x, y, width, height
}
}
public class whitePiece{
int xPos, yPos;
public void move(){}
public void draw(){}
}
First time putting whole code hope I edited it right hehe
Don't use CardLayout for this.
I'd use a JPanel that uses GridLayout to hold an 8x8 grid of chess square JPanels.
I'd place that in a JLayeredPane.
I'd add my pieces to the appropriate chess square JPanel.
When moving a piece, I'd lift it up to the drag layer of the JLayeredPane.
Also:
Don't draw directly on to a top-level window such as a JFrame.
Don't override the paint method.
Instead, if you must do drawing, override the paintComponent(Graphics g) of a JPanel or JComponent.
But again, if you create your chess board out of small JPanel chess squares, it is easy and natural to place pieces on the chess square and have it placed well.
For example, please check out my code here.
I am trying to add/draw a single Graphics object to an existing JPanel. I am generating 10 initial Graphics objects randomly sized and place in the panel, but would like to add additional drawn objects one a time, randomly sized and placed like the initial 10.
Currently, the AddNewDrawItem class is not rendering the new Graphics object.
Thank you for input.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
public class Painter{
private DrawingPanel dp = new DrawingPanel();
//constructor
public Painter(){
buildGUI();
}
private void buildGUI(){
JFrame frame = new JFrame();
frame.setLayout(new BorderLayout());
frame.setTitle("Paint drawing demonstration");
JPanel headerPanel = new JPanel();
headerPanel.add(new JLabel("The drawing panel is below"));
JButton addNew = new JButton("Add New Graphic");
addNew.addActionListener(new addNewClickHandler());
headerPanel.add(addNew);
frame.add(BorderLayout.NORTH,headerPanel);
frame.add(BorderLayout.SOUTH,this.dp);
frame.pack();
frame.setVisible(true);
}
class DrawingPanel extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.white);
int x, posx, posy, width, height;
for(x=0;x<=10;x++){
//even number differentiation
if(x % 2 == 0){
g.setColor(Color.red);
}else{
g.setColor(Color.blue);
}
Random rand = new Random();
posx = rand.nextInt(300);
posy = rand.nextInt(300);
width = rand.nextInt(40);
height = rand.nextInt(40);
//System.out.println("the ran x pos is: " + posx);
g.fillRect(posx, posy, width, height);
}//end for
}//end paintComponent
public Dimension getPreferredSize() {
return new Dimension(400,400);
}
}// end DrawingPanel
private class addNewClickHandler implements ActionListener{
public void actionPerformed(ActionEvent e){
System.out.print("in addNew_click_handler click handler");//trace debug
AddNewDrawItem newItem = new AddNewDrawItem();
newItem.repaint();
System.out.print("after repaint() in addNew_click_handler click handler");//trace debug
}
}
class AddNewDrawItem extends JPanel {
public void paintComponent(Graphics g) {
super.paintComponent(g);
this.setBackground(Color.white);
int posx, posy, width, height;
Random rand = new Random();
posx = rand.nextInt(300);
posy = rand.nextInt(300);
width = rand.nextInt(40);
height = rand.nextInt(40);
g.setColor(Color.cyan);
g.fillRect(posx, posy, width, height);
}//end paintComponent
}//end AddNewDrawItem
public static void main(String args[]){
new Painter();
}
}//end class Painter
You've got some problems with your code, one of which is that you've got program logic in your paintComponent method: the code randomly changes values that are displayed within this method, meaning your display will change when it repaints, whether you want it to or not. To see that this is so, try to resize your GUI and you'll see some psychedelic changes in the drawn red and blue rectangles.
Now as to your current problem, the solution to it is similar to the solution to the problem I describe above. I suggest...
that you create an ArrayList<Rectangle2D>,
that you create your random rectangles in your class's constructor so that they're created only once, and then place them in the ArrayList above.
that you iterate through this ArrayList in your JPanel's paintComponent method, drawing them as you go. This way paintComponent does nothing but paint which is as it should be,
that you create a MouseAdapter-derived object and add it as a MouseListener and MouseMotionListener to your DrawingPanel
that you use the listener above to create a new Rectangle2D object and when done add it to the ArrayList and call repaint on the DrawingPanel
that you activate the mouse adapter via your button's action listener.
I'll stop there, but I think you get the idea, and if you don't, please ask any questions you may have.