public class mouse extends JFrame {
private int x, y;
private JLabel label;
public mouse() {
JPanel panel = new JPanel();
addMouseMotionListener(new MouseMotion());
label = new JLabel();
panel.add(label);
setPreferredSize(new Dimension(400, 200));
add(panel, BorderLayout.SOUTH);
pack();
setVisible(true);
}
private class MouseMotion extends MouseMotionAdapter {
public void mouseMoved(MouseEvent e) {
x = e.getX();
y = e.getY();
label.setText("mouse coordinate " + "(" + x + "," + y + ")");
}}
public static void main(String[]args) {
mouse a = new mouse();
}
}
When I move mouse to border, it is not (0,0). Why? For example, I move mouse to top left corner, it shows (4,30) rather than (0,0).
Add the MouseListener or MouseMotionListener to the JFrame's contentPane, not the JFrame itself, else you have to worry about borders, menus, insets, and the like. For example:
getContentPane().addMouseMotionListener(new MouseMotion());
Also, please format your code so we can read it.
Related
i have a task to make an application wich will do the following:
If I move a mouse the coordinates should be shown on the status bar
If mouse is clicked then the only one button which is on a JPanel should move to coordinates of click
So the problem is that when i do mouse click - it's fine, button moves to coord's of click, but when i start moving mouse the button comes back to the original position
public class Window extends JFrame {
private JLabel statusBar;
private JPanel mainPanel, statusBarPanel;
JButton button;
public Window()
{
super("Window");
setSize(400,600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel=new JPanel();
statusBarPanel = new JPanel();
statusBar=new JLabel("Coords: ");
add(statusBarPanel, BorderLayout.SOUTH);
add(mainPanel,BorderLayout.CENTER);
mainPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
statusBarPanel.add(statusBar,BorderLayout.CENTER);
button = new JButton("Default text");
mainPanel.add(button);
MyMouseListener myMouseListener=new MyMouseListener();
mainPanel.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
statusBar.setText("Coords: ("+e.getX()+":"+e.getY()+")");
}
});
mainPanel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
super.mouseClicked(e);
button.setLocation(e.getX()-button.getWidth()/2,e.getY()-button.getHeight()/2);
}
});
mainPanel.setFocusable(true);
setVisible(true);
}
}
This is one of the rare cases where you don't want your panel to have a layout manager, since you need absolute positioning.
JPanel has a default layout manager which is a FlowLayout, and your call to setLocation will only have a temporary effect until the panel revalidates its content and places things where they were supposed to be initially.
See the following example with comments, it should give you the general idea :
public class Window extends JFrame {
private final JLabel statusBar;
private final JPanel mainPanel, statusBarPanel;
JButton button;
public Window() {
super("Window");
setSize(400, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainPanel = new JPanel();
mainPanel.setLayout(null);// no layout for absolute positioning
statusBarPanel = new JPanel();
statusBar = new JLabel("Coords: ");
add(statusBarPanel, BorderLayout.SOUTH);
add(mainPanel, BorderLayout.CENTER);
mainPanel.setBorder(new BevelBorder(BevelBorder.LOWERED));
statusBarPanel.add(statusBar, BorderLayout.CENTER);
button = new JButton("Default text");
// place the button "manually"
button.setBounds((int) (400 - button.getPreferredSize().getWidth()) / 2, 0,
(int) button.getPreferredSize().getWidth(),
(int) button.getPreferredSize().getHeight());
mainPanel.add(button);
mainPanel.addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(final MouseEvent e) {
super.mouseMoved(e);
statusBar.setText("Coords: (" + e.getX() + ":" + e.getY() + ")");
}
});
mainPanel.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(final MouseEvent e) {
super.mouseClicked(e);
button.setLocation((int) (e.getX() - button.getPreferredSize().getWidth() / 2),
(int) (e.getY() - button.getPreferredSize().getHeight() / 2));
}
});
mainPanel.setFocusable(true);
setVisible(true);
}
}
Background Information:
This is a Java project for Undergraduate Research at my school. I will be presenting this program on Sunday 4/23/2017. I am stuck on a specific part of my program. This program is not located in any textbook and was made from scratch.
Programmed using Eclipse Neon.2 on Windows 10.
Description:
This program is an animation window using JApplet. Displayed will be a single window which uses the border layout to organize my panels. I have 5 panels (2 sliders on the east and west, 1 radio button on the south, one title on the north, and the center is animation).
The problem area is the center panel, which is where the animation window is located. I have three classes that each create an animation of 16 balls. One class creates balls bouncing vertically, another the balls bounce horizontally, and finally the balls will bounce in random directions.
I am using a radio button panel to completely change the center panel, to display each different class upon clicking. It starts in the vertical class by default. I can get each class to display individually by commenting out one class and trying it with another.
The problem:
My action listener for the radio buttons IS properly communicating with the radio button being clicked. But the class is not changing and the panel is not being updated. With the way I have it set up now, the center panel is empty.
In the end i want to have my center panel able to display any of the three animation classes by clicking a radio button.
Disclaimer:
I have not properly programmed the logic for the horizontal or random class, but the vertical class works. The sliders are not functional.
Here is the code:
package NEWbounceBallPackage;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class NEWbounceBallClass extends JApplet{
private DrawingPanelRandom ballBounce3; //Center panel, if random bounce
private DrawingPanelHorizontal ballBounce2; //Center panel, if horizontal
//bounce
private DrawingPanelVertical ballBounce; //Center panel, if vertical bounce
private JPanel title; //North
private JPanel selectionButtons; //South
private JPanel ballSize; //West
private JPanel numberOfBalls; //East
private JSlider ballSizeSlider; //Component of ballSize panel
private JSlider numberOfBallsSlider; //Componenet of
private JRadioButton vertical; //button for DrawingPanelVertical
private JRadioButton horizontal; //button for DrawingPanelHorizontal
private JRadioButton random; //button for DrawingPanelRandom
public void init()
{
resize(1150,600); //resize main window
setLayout(new BorderLayout());
buildTitlePanel(); //builds north panel
buildBallBouncePanel(); //calls buildSelectionButtonsPanel()(radio
//buttons panel)
//buildSelectionButtonsPanel(); //being called in
//buildBallBouncePanel()
buildBallSizeSlider(); //builds west panel
buildNumberOfBallsSlider(); //builds east panel
add(title, BorderLayout.NORTH); //adds north panel to
//main window
//add(ballBounce, BorderLayout.CENTER); //will be called in
//buildSelectionButtonsPanel() inside of action listener
add(selectionButtons, BorderLayout.SOUTH); //adds south panel to
//main window
add(ballSize, BorderLayout.WEST); //adds west panel to
//main window
add(numberOfBalls, BorderLayout.EAST); //adds east panel to
//main window
}
private void buildTitlePanel() //creates north panel
{
title = new JPanel();
Font titleFont = new Font("Serrif", Font.BOLD, 17);
JLabel titleText = new JLabel("Bounce Ball Window");
titleText.setFont(titleFont);
title.add(titleText);
}
private void buildBallBouncePanel() //creates center panel by calling radio
//buttons
{
buildSelectionButtonsPanel();
}
public void buildSelectionButtonsPanel() //creates south panel (called by
buildBallBouncePanel()
{
selectionButtons = new JPanel();
vertical = new JRadioButton("Vertical Bounce");
horizontal = new JRadioButton("Horizontal Bounce");
random = new JRadioButton("Random Bounce");
ButtonGroup group = new ButtonGroup(); //groups buttons allowing
//only one to be selected
group.add(vertical);
group.add(horizontal);
group.add(random);
vertical.setSelected(true); //vertical button selected by default
selectionButtons.add(vertical);
selectionButtons.add(horizontal);
selectionButtons.add(random);
//ballBounce = new DrawingPanelVertical(); //(TEST) if you want to see
//animation work, uncomment line 76 and 77,
//add(ballBounce, BorderLayout.CENTER); //(TEST) this will only show
//the vertical bounce
vertical.addActionListener(new ActionListener() //action listener for
//vertical class
{
public void actionPerformed(ActionEvent event)
{
ballBounce = new DrawingPanelVertical(); //calls vertical
//class then adds to center panel
add(ballBounce, BorderLayout.CENTER);
System.out.print("Vertical Test");
}
}
);
horizontal.addActionListener(new ActionListener() //action listener for
//horizontal class
{
public void actionPerformed(ActionEvent event)
{
ballBounce2 = new DrawingPanelHorizontal(); //calls horizontal
//class then adds to center panel
add(ballBounce2, BorderLayout.CENTER);
System.out.print("Horizontal Test");
}
}
);
random.addActionListener(new ActionListener() //action listener for
//random class
{
public void actionPerformed(ActionEvent event)
{
ballBounce3 = new DrawingPanelRandom(); //calls random class
//then adds to center panel
add(ballBounce3, BorderLayout.CENTER);
System.out.print("Random Test");
}
}
);
}
private void buildBallSizeSlider() //creates west slider panel
{
ballSize = new JPanel();
ballSize.setLayout(new BorderLayout());
ballSizeSlider = new JSlider(JSlider.VERTICAL, 1, 8, 1);
JLabel title = new JLabel("Change Size of Ball");
ballSizeSlider.setPreferredSize(new Dimension(50,500));
ballSizeSlider.setMajorTickSpacing(1);
ballSizeSlider.setMinorTickSpacing(1);
ballSizeSlider.setPaintTicks(true);
ballSizeSlider.setPaintLabels(true);
//ballSizeSlider.addChangeListener(new SliderListener());
ballSize.add(title, BorderLayout.NORTH);
ballSize.add(ballSizeSlider, BorderLayout.CENTER);
}
//private class SliderListener implements ChangeListener
//{
// public void stateChanged(ChangeEvent e)
// {
// int sliderChoice;
// sliderChoice = ballSizeSlider.getValue();
// if(sliderChoice = )
//}
//}
private void buildNumberOfBallsSlider() //creates east slider panel
{
numberOfBalls = new JPanel();
numberOfBalls.setLayout(new BorderLayout());
numberOfBallsSlider = new JSlider(JSlider.VERTICAL, 0, 16, 8);
JLabel title = new JLabel("Adjust Number of Balls");
numberOfBallsSlider.setPreferredSize(new Dimension(50,500));
numberOfBallsSlider.setMajorTickSpacing(1);
numberOfBallsSlider.setMinorTickSpacing(1);
numberOfBallsSlider.setPaintTicks(true);
numberOfBallsSlider.setPaintLabels(true);
numberOfBalls.add(title, BorderLayout.NORTH);
numberOfBalls.add(numberOfBallsSlider, BorderLayout.CENTER);
}
}
package NEWbounceBallPackage;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class DrawingPanelVertical extends JPanel{
private final int X = 135; //starting position of first ball (all other ball
//starting positions are based from first ball)
private final int WIDTH = 40; //width of balls
private final int HEIGHT = 40; //height of balls
private final int TIME_DELAY = 40; //delays animation (increase to slow
//down)
private final int MOVE = 20; //dictates how quickly the ball moves during
//animation
private final int MINIMUM_Y = 50; //bottom limit of bounce
private final int MAXIMUM_Y = 400; //top limit of bounce
private int y = 400; //starting position of first ball (all other ball
//starting positions are based from first ball)
private boolean goingUp = true;
private Timer timer;
public DrawingPanelVertical()
{
setPreferredSize(new Dimension(800,500));
timer = new Timer(TIME_DELAY, new TimerListener());
timer.start();
}
public void paint(Graphics g)
{
super.paint(g);
g.drawRect(80, 0, 750, 500);
g.setColor(getBackground());
g.setColor(Color.black);
g.fillOval(X, y, WIDTH, HEIGHT);
g.setColor(Color.blue);
g.fillOval(X+50, y, WIDTH, HEIGHT);
g.setColor(Color.cyan);
g.fillOval(X+100, y, WIDTH, HEIGHT);
g.setColor(Color.darkGray);
g.fillOval(X+150, y, WIDTH, HEIGHT);
g.setColor(Color.gray);
g.fillOval(X+200, y, WIDTH, HEIGHT);
g.setColor(Color.green);
g.fillOval(X+250, y, WIDTH, HEIGHT);
g.setColor(Color.lightGray);
g.fillOval(X+300, y, WIDTH, HEIGHT);
g.setColor(Color.magenta);
g.fillOval(X+350, y, WIDTH, HEIGHT);
g.setColor(Color.orange);
g.fillOval(X+400, y, WIDTH, HEIGHT);
g.setColor(Color.pink);
g.fillOval(X+450, y, WIDTH, HEIGHT);
g.setColor(Color.red);
g.fillOval(X+500, y, WIDTH, HEIGHT);
g.setColor(Color.white);
g.fillOval(X+550, y, WIDTH, HEIGHT);
g.setColor(Color.yellow);
g.fillOval(X+600, y, WIDTH, HEIGHT);
}
private class TimerListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(goingUp)
{
if(y > MINIMUM_Y)
y = y - MOVE;
else
goingUp = false;
}
else
{
if(y < MAXIMUM_Y)
y = y + MOVE;
else
goingUp = true;
}
//resize(1300,600);
repaint();
//resize(1302,600);
}
}
}
But the class is not changing and the panel is not being updated.
Swing components by default have a size of (0, 0) so there is nothing to paint. You need to invoke the layout manager so the component can be given a size and location based on the rules of the layout manager.
So, when you add a component to a visible GUI the basic logic is:
panel.add(...);
panel.revalidate(); // invokes the layout manager
panel.repaint();
In the end i want to have my center panel able to display any of the three animation classes by clicking a radio button.
The better solution is to use a CardLayout and let the layout manager manage the visible panel. Read the section from the Swing tutorial on How to Use CardLayout for more information and working examples.
I am trying to get the code below to display the coordinates in info_panel but it is not working. How would I get the coordinates from the mouseListener from SimpleFrameViewWidget to be displayed in the info_panel? I am using setText right now... Thanks!
public static void main(String[] args) throws IOException {
Frame f = A7Helper.readFromURL("http://www.cs.unc.edu/~kmp/kmp.jpg");
f.setTitle("");
SimpleFrameViewWidget simple_widget = new SimpleFrameViewWidget(f);
JFrame main_frame = new JFrame();
main_frame.setTitle("Assignment 7 Pixel Inspector");
main_frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel top_panel = new JPanel();
top_panel.setLayout(new BorderLayout());
top_panel.add(simple_widget, BorderLayout.CENTER);
main_frame.setContentPane(top_panel);
JPanel info_panel = new JPanel();
info_panel.setLayout(new BorderLayout());
top_panel.add(info_panel, BorderLayout.SOUTH);
JLabel x_label = new JLabel("");
x_label.setHorizontalAlignment(SwingConstants.CENTER);
x_label.addMouseListener(simple_widget);
x_label.setText(simple_widget.getStringInfo());
info_panel.add(x_label);
main_frame.setContentPane(top_panel);
main_frame.pack();
main_frame.setVisible(true);
}
This is the code that has the mouseListener and mouseClick. Thanks in advance!
public class SimpleFrameViewWidget extends JPanel implements MouseListener {
private FrameView frame_view;
private String stringInfo;
public SimpleFrameViewWidget(Frame f) {
setLayout(new BorderLayout());
frame_view = new FrameView(f);
frame_view.addMouseListener(this);
add(frame_view, BorderLayout.CENTER);
JLabel title_label = new JLabel(f.getTitle());
add(title_label, BorderLayout.SOUTH);
}
#Override
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
stringInfo = "X: " + x + "Y: " + y;
}
public String getStringInfo(){
return stringInfo;
}
You Could...
Register another MouseListener to SimpleFrameViewWidget that simply feed the results directly to info_panel or have info_panel do it all for you....
Found this code in the internet, it was posted years ago, so I just decided to ask here for some clarifications for some lines I don't quite understand.
In the mousePressed method, what does he mean by:
chessPiece = null is he saying that if the JLabel chessPiece has a image in it then it should be changed to null?
Is chessBoard.findComponentAt(e.getX(), e.getY()) returns the JPanel square?
and lastly, when Component c gets its parent, who is the parent?
The whole code is below:
public class ChessGameDemo extends JFrame implements MouseListener, MouseMotionListener {
JLayeredPane layeredPane;
JPanel chessBoard;
JLabel chessPiece;
int xAdjustment;
int yAdjustment;
private static final String imageFolderPath = "src/resources/images/";
public ChessGameDemo() {
Dimension boardSize = new Dimension(600, 600);
// Use a Layered Pane for this this application
layeredPane = new JLayeredPane();
getContentPane().add(layeredPane);
layeredPane.setPreferredSize(boardSize);
layeredPane.addMouseListener(this);
layeredPane.addMouseMotionListener(this);
//Add a chess board to the Layered Pane
chessBoard = new JPanel();
layeredPane.add(chessBoard, JLayeredPane.DEFAULT_LAYER);
chessBoard.setLayout(new GridLayout(8, 8));
chessBoard.setPreferredSize(boardSize);
chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);
for (int i = 0; i < 64; i++) {
JPanel square = new JPanel(new BorderLayout());
chessBoard.add(square);
int row = (i / 8) % 2;
if (row == 0) {
square.setBackground(i % 2 == 0 ? Color.blue : Color.white);
} else {
square.setBackground(i % 2 == 0 ? Color.white : Color.blue);
}
}
//Add a few pieces to the board
JLabel piece = new JLabel(new ImageIcon(imageFolderPath + "/pieces/bdg.png"));
JPanel panel = (JPanel) chessBoard.getComponent(0);
panel.add(piece);
piece = new JLabel(new ImageIcon(imageFolderPath + "/pieces/belder.png"));
panel = (JPanel) chessBoard.getComponent(15);
panel.add(piece);
piece = new JLabel(new ImageIcon(imageFolderPath + "/pieces/bhero.png"));
panel = (JPanel) chessBoard.getComponent(16);
panel.add(piece);
piece = new JLabel(new ImageIcon(imageFolderPath + "/pieces/borb.png"));
panel = (JPanel) chessBoard.getComponent(20);
panel.add(piece);
}
public void mousePressed(MouseEvent e) {
chessPiece = null;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
if (c instanceof JPanel) {
return;
}
Point parentLocation = c.getParent().getLocation();
xAdjustment = parentLocation.x - e.getX();
yAdjustment = parentLocation.y - e.getY();
chessPiece = (JLabel) c;
chessPiece.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
chessPiece.setSize(chessPiece.getWidth(), chessPiece.getHeight());
layeredPane.add(chessPiece, JLayeredPane.DRAG_LAYER);
}
//Move the chess piece around
public void mouseDragged(MouseEvent me) {
if (chessPiece == null) {
return;
}
chessPiece.setLocation(me.getX() + xAdjustment, me.getY() + yAdjustment);
}
//Drop the chess piece back onto the chess board
public void mouseReleased(MouseEvent e) {
if (chessPiece == null) {
return;
}
chessPiece.setVisible(false);
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
if (c instanceof JLabel) {
Container parent = c.getParent();
parent.remove(0);
parent.add(chessPiece);
} else {
Container parent = (Container) c;
parent.add(chessPiece);
}
....
}
In the mousePiece method, what does he mean by: chessPiece = null is
he saying that if the JLabel chessPiece has a image in it then it
should be changed to null?
I assume you mean mousePressed. By using chessPiece = null, the author is de-referencing the variable, so what ever was assigned to it is no longer reachable through the is variable
Is chessBoard.findComponentAt(e.getX(), e.getY()) returns the JPanel square?
This depends. findComponentAt can search the current container and it's any of it's child containers until it finds a component at the specified position. Technquial, the author is ignoring the component that triggered the event (which should layeredPane) and is walking the chessBoard instead. I suspect they are doing this because if they used layeredPane it would return chessBoard instead.
The method is capable of returning JPanel, JLabel and possibly even null, but given the way that the components are laid out, it's a lower probability.
and lastly, when Component c gets its parent, who is the parent?
This depends. Based on my understanding of the code, I would say it's return a JPanel underneth the JLabel piece.
Have to say, there are easier ways to achieve the same result though...
In the mousePressed method, what does he mean by:
The purpose of the class is to drag a label from one square to another. So there is code in the mouseDragged and mouseReleased events to 1) do the dragging of the label on the layered pane and 2) drop the label onto the appropriate square.
However, if the user didn't click on a square containing a label then the above code should not be executed, so the chessPiece is initially set to null and the code in the above two method is only executed when a chessPiece was clicked on.
Is chessBoard.findComponentAt(e.getX(), e.getY()) returns the JPanel square?
If it returns a JPanel, then that means there is NO chessPiece (JLabel) on the square where the user clicked. Since there is no chessPiece there is nothing to be dragged.
If it returns a JLabel, then that means there IS a chessPiece where the user clicked. In this case addition code is executed to add the chessPiece to the layered pane so it can be dragged.
when Component c gets its parent, who is the parent?
It's the JPanel containing the label. Since the label is added to the layered pane for dragging it needs to be positioned at the same location on the layered pane relative to the panel square on the chessboard.
Here is a slightly updated version that checks the bounds of the chess piece as it is dragged so it can't be moved off of the chess board. Also adds the mouse listeners to the chess board not the layered pane so the findComponentAt() method is more consistent.
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class ChessBoard extends JLayeredPane implements MouseListener, MouseMotionListener
{
JLayeredPane layeredPane;
JPanel chessBoard;
JLabel chessPiece;
int xAdjustment;
int yAdjustment;
public ChessBoard()
{
Dimension boardSize = new Dimension(600, 600);
setPreferredSize( boardSize );
// Add a chess board to the Layered Pane
chessBoard = new JPanel();
chessBoard.setLayout( new GridLayout(8, 8) );
chessBoard.setPreferredSize( boardSize );
chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);
chessBoard.addMouseListener( this );
chessBoard.addMouseMotionListener( this );
add(chessBoard, JLayeredPane.DEFAULT_LAYER);
// Build the Chess Board squares
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
JPanel square = new JPanel( new BorderLayout() );
square.setBackground( (i + j) % 2 == 0 ? Color.red : Color.white );
chessBoard.add( square );
}
}
// Add a few pieces to the board
ImageIcon duke = new ImageIcon("dukewavered.gif"); // add an image here
JLabel piece = new JLabel( duke );
JPanel panel = (JPanel)chessBoard.getComponent( 0 );
panel.add( piece );
piece = new JLabel( duke );
panel = (JPanel)chessBoard.getComponent( 15 );
panel.add( piece );
}
/*
** Add the selected chess piece to the dragging layer so it can be moved
*/
public void mousePressed(MouseEvent e)
{
chessPiece = null;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
if (c instanceof JPanel) return;
Point parentLocation = c.getParent().getLocation();
xAdjustment = parentLocation.x - e.getX();
yAdjustment = parentLocation.y - e.getY();
chessPiece = (JLabel)c;
chessPiece.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
add(chessPiece, JLayeredPane.DRAG_LAYER);
setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
}
/*
** Move the chess piece around
*/
public void mouseDragged(MouseEvent me)
{
if (chessPiece == null) return;
// The drag location should be within the bounds of the chess board
int x = me.getX() + xAdjustment;
int xMax = chessBoard.getWidth() - chessPiece.getWidth();
x = Math.min(x, xMax);
x = Math.max(x, 0);
int y = me.getY() + yAdjustment;
int yMax = chessBoard.getHeight() - chessPiece.getHeight();
y = Math.min(y, yMax);
y = Math.max(y, 0);
chessPiece.setLocation(x, y);
}
/*
** Drop the chess piece back onto the chess board
*/
public void mouseReleased(MouseEvent e)
{
setCursor(null);
if (chessPiece == null) return;
// Make sure the chess piece is no longer painted on the layered pane
chessPiece.setVisible(false);
remove(chessPiece);
chessPiece.setVisible(true);
// The drop location should be within the bounds of the chess board
int xMax = chessBoard.getWidth() - chessPiece.getWidth();
int x = Math.min(e.getX(), xMax);
x = Math.max(x, 0);
int yMax = chessBoard.getHeight() - chessPiece.getHeight();
int y = Math.min(e.getY(), yMax);
y = Math.max(y, 0);
Component c = chessBoard.findComponentAt(x, y);
if (c instanceof JLabel)
{
Container parent = c.getParent();
parent.remove(0);
parent.add( chessPiece );
parent.revalidate();
}
else
{
Container parent = (Container)c;
parent.add( chessPiece );
parent.revalidate();
}
}
public void mouseClicked(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
private static void createAndShowUI()
{
JFrame frame = new JFrame("Chess Board");
frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
frame.add( new ChessBoard() );
frame.setResizable( false );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
I have no idea why it won't show. First I create an instance of the component and then add it to a certain element in a two-dimensional JPanel array. Then I loop through that array and add each JPanel to another JPanel container which is to hold all the JPanels.
I then add that final container to my JFrame window and set visibility to true, it should be visible?
public class View extends JFrame {
Board gameBoard;
JFrame gameWindow = new JFrame("Chess");
JPanel gamePanel = new JPanel();
JPanel[][] squarePanel = new JPanel[8][8];
JMenuBar gameMenu = new JMenuBar();
JButton restartGame = new JButton("Restart");
JButton pauseGame = new JButton("Pause");
JButton log = new JButton("Log");
View(Board board){
gameWindow.setDefaultCloseOperation(EXIT_ON_CLOSE);
gameWindow.setSize(400, 420);
gameWindow.getContentPane().add(gamePanel, BorderLayout.CENTER);
gameWindow.getContentPane().add(gameMenu, BorderLayout.NORTH);
gameMenu.add(restartGame);
gameMenu.add(pauseGame);
gameMenu.add(log);
gameBoard = board;
drawBoard(gameBoard);
gameWindow.setResizable(false);
gameWindow.setVisible(true);
}
public void drawBoard(Board board){
for(int row = 0; row < 8; row++){
for(int col = 0; col < 8; col++){
Box box = new Box(board.getSquare(col, row).getColour(), col, row);
squarePanel[col][row] = new JPanel();
squarePanel[col][row].add(box);
}
}
for(JPanel[] col : squarePanel){
for(JPanel square : col){
gamePanel.add(square);
}
}
}
}
#SuppressWarnings("serial")
class Box extends JComponent{
Color boxColour;
int col, row;
public Box(Color boxColour, int col, int row){
this.boxColour = boxColour;
this.col = col;
this.row = row;
repaint();
}
protected void paintComponent(Graphics drawBox){
drawBox.setColor(boxColour);
drawBox.drawRect(50*col, 50*row, 50, 50);
drawBox.fillRect(50*col, 50*row, 50, 50);
}
}
A final question as well. Notice how each Box component has a position, what happens to the position when I add the component to a JPanel and add the JPanel to my JFrame?
Does it still have the same position in relation to the other Box components?
I tried extending JPanel instead, got a small 10x10 pix gray box under my menu. Atleast a start
When you use a JComponent the preferred size is (0, 0) which is why you see nothing.
When you use a JPanel is uses a FlowLayout by default and the FlowLayout has a 5 pixel gap before/after each component added to the panel. Since you don't add any components the preffered size is just the gap so you get a size of (10, 10).
Therefore, when you do custom painting you need to override the getPreferredSize() method to return a proper value for the custom painting you intend to implement.
Edit:
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class ChessBoard extends JFrame implements MouseListener, MouseMotionListener
{
JLayeredPane layeredPane;
JPanel chessBoard;
JLabel chessPiece;
int xAdjustment;
int yAdjustment;
public ChessBoard()
{
Dimension boardSize = new Dimension(600, 600);
// Use a Layered Pane for this this application
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize( boardSize );
layeredPane.addMouseListener( this );
layeredPane.addMouseMotionListener( this );
getContentPane().add(layeredPane);
// Add a chess board to the Layered Pane
chessBoard = new JPanel();
chessBoard.setLayout( new GridLayout(8, 8) );
chessBoard.setPreferredSize( boardSize );
chessBoard.setBounds(0, 0, boardSize.width, boardSize.height);
layeredPane.add(chessBoard, JLayeredPane.DEFAULT_LAYER);
// Build the Chess Board squares
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
JPanel square = new JPanel( new BorderLayout() );
square.setBackground( (i + j) % 2 == 0 ? Color.red : Color.white );
chessBoard.add( square );
}
}
// Add a few pieces to the board
ImageIcon duke = new ImageIcon("dukewavered.gif"); // add an image here
JLabel piece = new JLabel( duke );
JPanel panel = (JPanel)chessBoard.getComponent( 0 );
panel.add( piece );
piece = new JLabel( duke );
panel = (JPanel)chessBoard.getComponent( 15 );
panel.add( piece );
}
/*
** Add the selected chess piece to the dragging layer so it can be moved
*/
public void mousePressed(MouseEvent e)
{
chessPiece = null;
Component c = chessBoard.findComponentAt(e.getX(), e.getY());
if (c instanceof JPanel) return;
Point parentLocation = c.getParent().getLocation();
xAdjustment = parentLocation.x - e.getX();
yAdjustment = parentLocation.y - e.getY();
chessPiece = (JLabel)c;
chessPiece.setLocation(e.getX() + xAdjustment, e.getY() + yAdjustment);
layeredPane.add(chessPiece, JLayeredPane.DRAG_LAYER);
layeredPane.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
}
/*
** Move the chess piece around
*/
public void mouseDragged(MouseEvent me)
{
if (chessPiece == null) return;
// The drag location should be within the bounds of the chess board
int x = me.getX() + xAdjustment;
int xMax = layeredPane.getWidth() - chessPiece.getWidth();
x = Math.min(x, xMax);
x = Math.max(x, 0);
int y = me.getY() + yAdjustment;
int yMax = layeredPane.getHeight() - chessPiece.getHeight();
y = Math.min(y, yMax);
y = Math.max(y, 0);
chessPiece.setLocation(x, y);
}
/*
** Drop the chess piece back onto the chess board
*/
public void mouseReleased(MouseEvent e)
{
layeredPane.setCursor(null);
if (chessPiece == null) return;
// Make sure the chess piece is no longer painted on the layered pane
chessPiece.setVisible(false);
layeredPane.remove(chessPiece);
chessPiece.setVisible(true);
// The drop location should be within the bounds of the chess board
int xMax = layeredPane.getWidth() - chessPiece.getWidth();
int x = Math.min(e.getX(), xMax);
x = Math.max(x, 0);
int yMax = layeredPane.getHeight() - chessPiece.getHeight();
int y = Math.min(e.getY(), yMax);
y = Math.max(y, 0);
Component c = chessBoard.findComponentAt(x, y);
if (c instanceof JLabel)
{
Container parent = c.getParent();
parent.remove(0);
parent.add( chessPiece );
parent.validate();
}
else
{
Container parent = (Container)c;
parent.add( chessPiece );
parent.validate();
}
}
public void mouseClicked(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public static void main(String[] args)
{
JFrame frame = new ChessBoard();
frame.setDefaultCloseOperation( DISPOSE_ON_CLOSE );
frame.setResizable( false );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
In the past, I have solved this by extending JPanel instead of JComponent. I found an good example here. Here's an adaptation of it which will draw a box:
public class Box extends JPanel {
Color color;
public Box (Color c, int w, int h) {
color = color;
setSize(w, h);
}
#Override
public void paintComponent(Graphics g) {
g.setColor(color);
g.drawOval(0, 0, getWidth(), getHeight());
}
...
This isn't exactly like your code above, but hopefully it'll get you started in the right direction!
A quick note (original response): the example above View is a JFrame which is never made visible. Instead, the class variable gameWindow is used. It would be good practice to make the top-level class the visible window.