JLabel duplicates itself - java

I'm trying to replicate an existing game for learning purposes. The code below creates a JFrame with squares that will be filled with labels and images, however, the "Start" label seems to replicate itself. I have some experience with Java, but I'm still a student. (Nearly no experience with Swing). I added the label to the frame instead of the panel because the squares I drew hide the label. Thanks :D
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Test{
public static void main(String[] args){
JFrame frame = new JFrame("Miau");
MyPanel panel = new MyPanel();
frame.setVisible(true);
frame.setSize(600,600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setVisible(true);
JLabel labelstart = new JLabel("Start");
frame.add(labelstart);
labelstart.setLocation(100, 100);
labelstart.setSize(30,14);
}
}
class MyPanel extends JPanel {
public void paint(Graphics g) {
g.setColor(Color.black);
//g.fillRect(10,10,570,100);
int posx = 10;
int posy = 120;
g.drawRect(10,10,570,100);
g.drawRect(posx,posy,570,430);
int size = 5;
int width = 570/size;
int height = 430/size;
for(int m=0;m<size;m++){
for(int n=0;n<size;n++){
g.drawRect(posx,posy,width,height);
posx += width;
}
posx = 10;
posy += height;
}
}
}

I found a valid solution to my problem. I used label.setBounds(positionx,positiony,boundx,boundy). I'm trying to make a simple game that uses a refreshing JPanel, and it's working.

Related

Add delay of 1 second between each arc of a RainBow

Hi I am here add delay BETWEEN the formation of each arc of a Rainbow using Thread.delay() so that it look like an animation. When I am using Thread.delay() it delays the whole process. Is there any other method or I am doing it wrong. Please help me solve the problem
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;
import javax.swing.*;
public class RainBow2{
static int x,y,z;
static RainBowPanel rainBow = new RainBowPanel();
static StdRainBow stdRainBow = new StdRainBow();
static JTextField xCo = new JTextField(4);
static JTextField yCo = new JTextField(4);
static JTextField angle = new JTextField(4);
static JFrame frame;
public static void main(String[] args){
Color color = new Color(135,206,250);
frame = new JFrame("Rainbow");
JPanel panel = new JPanel();
JButton draw = new JButton("Draw RainBow");
draw.addActionListener(new ListenButton());
JLabel lab1 = new JLabel("X-Coordinate");
JLabel spaceLab = new JLabel(" ");
JLabel lab2 = new JLabel("Y-Coordinate");
JLabel angleLab = new JLabel("Initial Angle");
JButton chButton = new JButton("Change Color");
chButton.addActionListener(new ListenButton());
panel.setBackground(color);
panel.add(angleLab);
panel.add(angle);
panel.add(lab1);
panel.add(xCo);
panel.add(spaceLab);
panel.add(lab2);
panel.add(yCo);
panel.add(draw);
panel.add(spaceLab);
panel.add(chButton);
frame.getContentPane().add(BorderLayout.SOUTH,panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1366,740);
frame.setVisible(true);
rainBow.addMouseListener(new RainBowList());
frame.getContentPane().add(rainBow);
}
static class RainBowList extends MouseAdapter implements MouseMotionListener{
public void mouseClicked(MouseEvent e){
x = e.getX();
y = e.getY();
rainBow.drawing(x, y, 0);
}
}
static class ListenButton implements ActionListener{
public void actionPerformed(ActionEvent a){
if(a.getActionCommand().equals("Draw RainBow")){
x = Integer.parseInt(xCo.getText());
y = Integer.parseInt(yCo.getText());
z = Integer.parseInt(angle.getText());
rainBow.drawing(x, y,z);
}
if(a.getActionCommand().equals("Change Color")){
rainBow.drawing(x, y,z);
}
}
}
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.awt.event.*;
public class RainBowPanel extends JPanel{
int x,y,z;
public void drawing(int xx, int yy, int zz){
Color color = new Color(135,206,250);
setBackground(color);
z = zz;
x = xx;
y = yy;
repaint();
}
public void paintComponent(Graphics g){
super.paintComponent(g);
int length = 300;
int width = 300;
x = x-length/2;
y = y-width/2;
for(int i =0 ; i< 7;i++){
Color color = new Color((int)(Math.random()*255),(int)(Math.random()*255),(int)(Math.random()*255));
g.setColor(color);
g.fillArc(x,y,length ,width ,z,180 );
x=x+15;
y=y+15;
length = (length-30);
width = (width-30);
try{
Thread.sleep(200);
}catch(Exception e){
}
}
}
}
}
When I am using Thread.delay() it delays the whole process.
A painting method is for painting only. You should not be causing the Thread to delay. This will prevent the GUI from repainting itself until the entire loop is finished executing.
Instead you can use a Swing Timer to schedule the repainting.
Instead of doing the painting in the paintComponent() you should maybe paint to a BufferedImage. Then you can display the Image in an ImageIcon on a JLabel.
So when the Timer event is generated you paint a color of the rainbow. After all 7 colors are painted you stop the Timer.
Read the section from the Swing tutorial on How to Use Swing Timers for more information and examples.

Java Swing - Position measure unit?

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.

Maintain component size by centring with buffers

I am building a small chess board for tactics, it would be a fun way to reflect upon on interests (programming and chess).
One problem I have currently face, although solved, is maintaining the board aspect ratio of 1:1.
The Board extends JPanel. Due to a problem with constraints, I have opted towards maintaining the board's physical size rather than it's rendered size. This would lead to faster operations when actually being used.
What I want it to look like, and have achieved:
The way I achieved this though seemed very hackish and is poor code by Skeet standards (thank you based Skeet).
public Frame() {
final JFrame frame = new JFrame("Chess");
final JPanel content = new JPanel(new BorderLayout());
final JPanel boardConfine = new JPanel(new BorderLayout());
final Board board = new Board();
boardConfine.addComponentListener(new ComponentAdapter() {
#Override
public void componentResized(ComponentEvent e) {
int min = Math.min(boardConfine.getWidth(), boardConfine.getHeight());
int xBuffer = (boardConfine.getWidth() - min) / 2;
int yBuffer = (boardConfine.getHeight() - min) / 2;
board.setBounds(xBuffer, yBuffer, min, min);
}
});
boardConfine.add(board, BorderLayout.CENTER);
content.setBackground(new Color(205, 205, 205));
content.add(boardConfine, BorderLayout.CENTER);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setContentPane(content);
frame.pack();
frame.setVisible(true);
}
As seen above, I manually set the board's size and location. Even I have stated exhaustively that this shouldn't ever be done, but I couldn't find a solution to work. I need the board to fill the maximum possible area, yet maintain the aspect ratio.
If there are any suggestions (either code or concepts) you can provide, I really thank you for taking the time to help me with this elitist conundrum.
Although not a complete solution, the example below scales the board to fill the smallest dimension of the enclosing container. Resize the frame to see the effect.
Addendum: The ideal solution would be Creating a Custom Layout Manager, where you have access to the enclosing container's geometry, and setBounds() can maintain the desired 1:1 aspect ratio. A variation of GridLayout may be suitable. Grid coordinates can be calculated directly, as shown here.
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
* #see https://stackoverflow.com/a/19531648/230513
*/
public class Test {
private static class MyPanel extends JPanel {
private static final int N = 8;
private static final int TILE = 48;
#Override
public Dimension getPreferredSize() {
return new Dimension(N * TILE, N * TILE);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.gray);
int w = this.getWidth();
int h = this.getHeight();
int tile = Math.min(w, h) / N;
for (int row = 0; row < N; row++) {
for (int col = 0; col < N; col++) {
if ((row + col) % 2 == 0) {
g.fillRect(col * tile, row * tile, tile, tile);
}
}
}
}
}
private void display() {
JFrame f = new JFrame("Test");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(new MyPanel());
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Test().display();
}
});
}
}

Multi-threaded bouncing balls, issue displaying balls

I'm trying to use multithreading to draw balls that bounce around inside a JFrame. I can get the coordinates of each ball to update and print out, but I can't get the balls to display. I'm not very strong in graphics, and I'm not quite sure what I'm missing. I think I need to add each instance of Ball to the panel I have inside my frame, but when I tried that it didn't make a difference. I also have a class used to view the JFrame, that I've omitted. What am I missing here?
Ball
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JPanel;
public class Ball extends JPanel implements Runnable {
JPanel pan;
private static int radius = 10;
private Color color;
private int xPos;
private int yPos;
private int dx;
private int dy;
Dimension d;
public Ball(JPanel p) {
Random r = new Random();
this.pan = p;
this.d = pan.getSize();
xPos = r.nextInt(d.width-50)+25;
yPos = r.nextInt(d.height-50)+25;
dx = r.nextInt(3)+1;
dy = r.nextInt(3)+1;
color = new Color(r.nextInt(255*255*255));
paintComponent(pan.getGraphics());
}
public void move() {
xPos += dx;
yPos += dy;
if (xPos+radius <= 0 || xPos+radius >= d.width)
dx = -dx;
if (yPos+radius <= 0 || yPos+radius >= d.height)
dy = -dy;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillOval(xPos-radius, yPos-radius, 2*radius, 2*radius);
g.dispose();
}
public void animate() {
paintComponent(pan.getGraphics());
move();
//pan.validate();//this didn't
//pan.repaint();// work
try {
Thread.sleep(40);
} catch (InterruptedException e) {}
}
public void run() {
while(true)
animate();
}
}
BallTracker
import java.util.ArrayList;
public class BallTracker {
private ArrayList<Ball> balls;
public BallTracker() {
balls = new ArrayList<Ball>();
}
public void addBall(Ball b) {
balls.add(b);
Thread t = new Thread(b);
t.start();
}
}
BallFrame
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class BallFrame extends JFrame {
public static final int WIDTH = 500;
public static final int HEIGHT = 550;
private BallTracker tracker;
private JPanel ballPanel;
private JPanel buttonPanel;
public BallFrame() {
super("BallFrame");
tracker = new BallTracker();
// set up ball panel
ballPanel = new JPanel();
ballPanel.setSize(WIDTH, 500);
// listener to add a new ball to tracker
class bListener implements ActionListener {
public void actionPerformed( ActionEvent event ) {
Ball b = new Ball(ballPanel);
tracker.addBall(b);
}
}
// set up button panel
buttonPanel = new JPanel();
buttonPanel.setSize(WIDTH, 50);
JButton addBallButton = new JButton();
addBallButton.setText("Add ball");
addBallButton.addActionListener(new bListener());
buttonPanel.add(addBallButton);
// add panels to frame
add(buttonPanel, BorderLayout.SOUTH);
add(ballPanel, BorderLayout.CENTER);
setSize( WIDTH, HEIGHT );
}
}
It seems your ball extends jpanel and has a paint method, but your ballPanel would need to do the painting and your ball doesn't really seem to need to be a panel at all.
set up ball panel
ballPanel = new JPanel();
ballPanel.setSize(WIDTH, 500);
I was mainly looking for issues with the way I am trying to draw here, and why I don't see a ball
The Ball isn't added to any panel.
Even when you do add the ball to the panel, the Ball has no size, so there is nothing to paint.
Even if you did give the panel a size only one Ball would ever show up because you Ball panel is opaque.
Your code is attempting to paint the ball at a location within the ball panel. Instead you should be painting the ball at location (0, 0) within your ball panel and then set the location of the Ball panel relative to the parent container.
The parent container should be using a null layout so you can randomly set the location of your Ball panel.
I'm sure there are other issues as well...
I suggest you forget about multithreading and start with the basics of custom painting and using Timers.

Trying to add a dynamically positioned image in a JPanel on a button click

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.

Categories

Resources