I am working on Battleship project right now. I created two panels which i put in one frame. First panel is grid of buttons, and second panel is consist of draggable ship images. All I want, is when I drag the image into the certain button, it would appear on that button. In other words, i want just a simple addition of image into the JButton by dragging image into it.
Here is the full code:
import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class BattleShip extends JFrame{
public BattleShip() throws IOException {
this.setResizable(false);
this.pack();
JPanel panelLeft = new JPanel();
JPanel panelRight = new JPanel();
panelLeft.setSize(500, 650);
panelRight.setSize(200,650);
panelRight.setBorder(BorderFactory.createLineBorder(Color.RED, 7));
panelRight.setBackground(Color.WHITE);
panelLeft.setLayout(new GridLayout(11,11));
panelRight.setLayout(null);
BufferedImage myPicture = ImageIO.read(new File("/home/hikmet/Desktop/595a7960d639a15d096a226d.png"));
BufferedImage[] resized = new BufferedImage[14];
for (int i = 0; i < 14; ++i) {
resized[i] = resize(myPicture, 20, 30);
}
JLabel[] img = new JLabel[14];
for (int i = 0; i < 14; ++i) {
img[i] = new JLabel((new ImageIcon(resized[i])));
}
Dimension size = img[0].getPreferredSize();
for (int i = 0; i < 14; ++i) {
panelRight.add(img[i]);
img[i].setBounds(7 + i * 50, 7, size.width, size.height);
}
JButton button[][] = new JButton[11][11];
for (int i = 0; i < 11; i++) {
for (int j = 0; j < 11; j++) {
button[i][j] = new JButton();
panelLeft.add(button[i][j]);
}
}
button[1][0].setText("A"); button[0][1].setText("1");
button[2][0].setText("B"); button[0][2].setText("2");
button[3][0].setText("C"); button[0][3].setText("3");
button[4][0].setText("D"); button[0][4].setText("4");
button[5][0].setText("E"); button[0][5].setText("5");
button[6][0].setText("F"); button[0][6].setText("6");
button[7][0].setText("G"); button[0][7].setText("7");
button[8][0].setText("H"); button[0][8].setText("8");
button[9][0].setText("I"); button[0][9].setText("9");
button[10][0].setText("J"); button[0][10].setText("10");
for (int i = 0; i < 14; i++) { //applying mouseEvent to each image
MouseHandler movement = new MouseHandler(img[i]);
}
this.setTitle("BattleShip");
this.setSize(700,700);
this.setLayout(new GridLayout(2,4));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.getContentPane().add(panelLeft);
this.getContentPane().add(panelRight);
}
//method for just resizing the size of image
private static BufferedImage resize(BufferedImage myPicture, int height, int width) {
Image tmp = myPicture.getScaledInstance(width, height, Image.SCALE_SMOOTH);
BufferedImage resized = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = resized.createGraphics();
g2d.drawImage(tmp,0,0,null);
g2d.dispose();
return resized;
}
//Class for handling mouseEvents
public class MouseHandler implements MouseMotionListener {
private int x, y;
public MouseHandler(JLabel img){
img.addMouseMotionListener(this);
}
#Override
public void mouseDragged(MouseEvent mouseEvent) {
mouseEvent.getComponent().setLocation((mouseEvent.getX()+mouseEvent.getComponent().getX())-x, (mouseEvent.getY()+mouseEvent.getComponent().getY())-y);
}
#Override
public void mouseMoved(MouseEvent mouseEvent) {
x = mouseEvent.getX();
y = mouseEvent.getY();
}
}
//Main class
public class Main {
public static void main(String[] args) throws IOException {
new BattleShip();
}
}
Hope someone will help me :)
You can specify the property to be dragged when you use the TransferHandler class:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class DragIcon extends JPanel
{
public DragIcon()
{
setLayout( new BorderLayout(40, 20) );
TransferHandler iconHandler = new TransferHandler( "icon" );
// TransferHandler iconHandler = new TransferHandler( "text" );
MouseListener dragListener = new DragMouseAdapter();
JLabel dragLabel = new JLabel("Drag");
dragLabel.setTransferHandler( iconHandler );
dragLabel.addMouseListener(dragListener);
dragLabel.setIcon( new ImageIcon("copy16.gif") );
dragLabel.setHorizontalAlignment(JLabel.CENTER);
add(dragLabel, BorderLayout.PAGE_START);
JLabel label = new JLabel("Label");
label.setTransferHandler( iconHandler );
add(label, BorderLayout.LINE_START);
JButton button = new JButton("Button");
button.setTransferHandler( iconHandler );
add(button, BorderLayout.LINE_END);
}
private class DragMouseAdapter extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
JComponent c = (JComponent)e.getSource();
TransferHandler handler = c.getTransferHandler();
handler.exportAsDrag(c, e, TransferHandler.COPY);
}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("Drag Icon");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new DragIcon());
frame.setLocationByPlatform( true );
frame.pack();
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
}
}
Related
Inside my borderlayout, i have JPanels which are referenced by the array theGrid. In a separate function, I want to change the look of a JPanel, so I change how the specific JPanel should be painted. The problem im having is that i dont know how i now make it paint this new version of the JPanel?
I have looked at other questions and have tried using .revalidate, .validate, .repaint(), etc on mainPanel or on contentPane, or on both but none will get the new version of the JPanel i created to be drawn on.
In the constructor below I setup the grid and how it will fit into the rest of the JFrame
public class GraphicDisplay extends JFrame {
private static int ROWS = 6;
private static int COLS = 7;
private JPanel[][] theGrid = new JPanel[ROWS][COLS];
private JPanel mainPanel = new JPanel(new GridLayout(ROWS, COLS));
private Container contentPane;
public GraphicDisplay() {
for (int i = 0; i < theGrid.length; i++) { //Initialize theGrid (with blanks)
for (int j = 0; j < theGrid[i].length; j++) {
theGrid[i][j] = new JPanel();
}
}
//add them to the JFrame
contentPane = getContentPane();
contentPane.setLayout(new BorderLayout());
JPanel boardElements = new JPanel();
boardElements.setLayout(new BoxLayout(boardElements, BoxLayout.Y_AXIS)); //vertical layout for the two parts, theGrid itself and then the
// button which goes underneath,
final int SPACE = 3;
final Color COLORCHOICE = Color.BLACK;
mainPanel.setBorder(BorderFactory.createEmptyBorder(SPACE, SPACE, SPACE, SPACE));
mainPanel.setBackground(COLORCHOICE);
JPanel[][] panels = new JPanel[ROWS][COLS];
for (int i = 0; i < panels.length; i++) {
for (int j = 0; j < panels[i].length; j++) {
panels[i][j] = new JPanel(new GridLayout(1, 1, 1, 1));
panels[i][j].setBackground(COLORCHOICE);
panels[i][j].setBorder(BorderFactory.createEmptyBorder(SPACE, SPACE, SPACE, SPACE));
mainPanel.add(panels[i][j]);
panels[i][j].add(theGrid[i][j]);
}
}
//adding the grid to the vertical layout
boardElements.add(mainPanel);
//adding the button which will go directly under the grid
boardElements.add(new JButton("Button"));
contentPane.add(boardElements, BorderLayout.CENTER);
}
The function below which is in the same class is suppose to update the grid by adding a dot at the point 3,3 (but the problem i don't see any visible change)
public void addDotToGrid() {
//theGrid[3][3] reference was added to the panels array which is part of the layout, so I would of thought by changing the value of it here would then change this JPanel on the UI
theGrid[3][3] = new JPanel() {
public void paintComponent( Graphics g) {
//g.setColor(Color.RED);
int y = 0;
int diameter = getWidth() -10;
int x = (getWidth()/2) - (diameter/2);
super.paintComponent(g);
Graphics2D g2d = (Graphics2D)g;
// Assume x, y, and diameter are instance variables.
Ellipse2D.Double circle = new Ellipse2D.Double(x, y, diameter, diameter);
g2d.fill(circle);
}
};
}
Main method in another class where GraphicDisplay object is created
public static void main(String[] args) {
GraphicDisplay display2 = new GraphicDisplay();
display2.setSize(600, 600);
display2.setVisible(true);
display2.addDotToGrid();
}
The problem is the grid is displayed but the addDotToGrid() does not change anything and there isn't a dot added to the gird
You're changing a JPanel held by your theGrid array, but this has no effect on the JPanels displayed in the GUI, and this gets to the key difference between a variable and a reference or object -- changing the object that a variable refers to has no effect on the object that it previously referred to. Your solution is to change the JPanel held by the grid.
One way to do this is to give all of them paintComponent methods that draw what you want, but have them controlled by a boolean, and then change the boolean variable of the panel of interest.
If this were my GUI though, I'd create a grid of JLabels and simply swap ImageIcons where and when I want -- keep it simple as possible!
For example
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import javax.swing.*;
#SuppressWarnings("serial")
public class MyGridEg extends JPanel {
private static final int SPACE = 6;
private static final int ROWS = 6;
private static final int COLS = 7;
private static final int IMG_W = 80;
private static final int SML_GAP = 3;
private static final Color IMG_BACKG = new Color(240, 240, 240);
private static final String TITLE = "Click on a Cell";
private JLabel[][] labelGrid = new JLabel[ROWS][COLS];
private Icon blankIcon = createIconDisk(new Color(0, 0, 0, 0));
private Icon redIcon = createIconDisk(Color.RED);
public MyGridEg() {
MyMouse myMouse = new MyMouse();
JPanel gridHolder = new JPanel(new GridLayout(ROWS, COLS, SPACE, SPACE));
gridHolder.setBackground(Color.BLACK);
for (int i = 0; i < labelGrid.length; i++) {
for (int j = 0; j < labelGrid[i].length; j++) {
JLabel label = new JLabel(blankIcon);
label.addMouseListener(myMouse);
labelGrid[i][j] = label;
gridHolder.add(label);
}
}
gridHolder.setBorder(BorderFactory.createLineBorder(Color.black, SPACE));
JLabel titleLabel = new JLabel(TITLE, SwingConstants.CENTER);
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 20));
JButton clearButton = new JButton(new ClearAction("Clear"));
JPanel btnPanel = new JPanel();
btnPanel.add(clearButton);
setLayout(new BorderLayout());
add(gridHolder, BorderLayout.CENTER);
add(btnPanel, BorderLayout.PAGE_END);
add(titleLabel, BorderLayout.PAGE_START);
}
private Icon createIconDisk(Color color) {
BufferedImage img = new BufferedImage(IMG_W, IMG_W, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setBackground(IMG_BACKG);
g2.clearRect(0, 0, IMG_W, IMG_W);
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(color);
int x = SML_GAP;
int y = x;
int width = IMG_W - 2 * x;
int height = IMG_W - 2 * y;
g2.fillOval(x, y, width, height);
g2.dispose();
return new ImageIcon(img);
}
private class MyMouse extends MouseAdapter {
#Override
public void mousePressed(MouseEvent e) {
JLabel selected = (JLabel) e.getSource();
Icon icon = selected.getIcon() == blankIcon ? redIcon : blankIcon;
selected.setIcon(icon);
}
}
private class ClearAction extends AbstractAction {
public ClearAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
for (JLabel[] labelRow : labelGrid) {
for (JLabel cell : labelRow) {
cell.setIcon(blankIcon);
}
}
}
}
private static void createAndShowGui() {
MyGridEg mainPanel = new MyGridEg();
JFrame frame = new JFrame("MyGridEg");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
The key to this code is that I'm not swapping out JLabels or JPanels but rather I'm keeping the JLabels the same, but am changing their state. This way if I change the state of the JLabels held by the 2D array, labelGrid, this is reflected by changes in the view, as I do in the ClearAction class that the clearButton JButton calls:
private class ClearAction extends AbstractAction {
public ClearAction(String name) {
super(name);
}
#Override
public void actionPerformed(ActionEvent e) {
for (JLabel[] labelRow : labelGrid) {
for (JLabel cell : labelRow) {
cell.setIcon(blankIcon);
}
}
}
}
I have one class Names and it has a JTextField. I am trying to place getText from this textfield and save it in the variable nameString1. I then want the other class Game to call Names and place the string collected from ``the JTextField onto a label. For some reason it is not displaying. Please let me know if there are any rookie errors, I am only year 10.
Names
package com.aqagame.harrykitchener;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
public class Names
{
private JLabel player1Label;
private JTextField player1Input;
private JButton nextButton;
public String nameString1;
public Names()
{
final JFrame window = new JFrame("Player 1 username");
JPanel firstPanel = new JPanel(new GridLayout(3,2));
player1Label = new JLabel("Player 1");
player1Input = new JTextField();
nextButton = new JButton("Next");
firstPanel.add(player1Label);
firstPanel.add(player1Input);
firstPanel.add(nextButton);
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
nameString1 = player1Input.getText();
System.out.print(nameString1);
Names2 names2Call = new Names2();
window.dispose();
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(firstPanel);
window.setSize(250, 150);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Names();
}
});
}
}
Game
package com.aqagame.harrykitchener;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Game
{
private JLabel player1Str, player2Str;
public Game()
{
JFrame window = new JFrame ("Main Game");
JPanel drawPanel = new JPanel(new GridLayout(3, 1))
{
public void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
int width = getWidth() / 4;
int height = getHeight() / 11;
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
}
};
Names namesCall2 = new Names();
player1Str = new JLabel(namesCall2.nameString1);
drawPanel.add(player1Str);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(drawPanel);
window.setSize(700, 600);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Game();
}
});
}
}
The problem is that you are setting the label without getting the textfield text. The JLabel on your Game wont change by the time you click the button..
Okie I made some change in you classes What I did is that I maid an interface which will be called when your button is pressed
Here is the interface:
public interface Lawl {
public void changename(String name);
}
I then implemented this interface to the game:
public class Game implements Lawl
{
private JLabel player1Str, player2Str;
JPanel drawPanel;
Names namesCall2;
public Game()
{
JFrame window = new JFrame ("Main Game");
drawPanel = new JPanel(new GridLayout(3, 1))
{
public void paintComponent(Graphics g)
{
Graphics2D g2d = (Graphics2D) g;
int width = getWidth() / 4;
int height = getHeight() / 11;
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
for(int i = 0; i<4; i++)
{
g.drawLine(i * width, 0, i * width, 700);
}
}
};
// Names namesCall2 = new Names(this);
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
namesCall2 = new Names(Game.this);
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(drawPanel);
window.setSize(700, 600);
window.setLocationRelativeTo(null);
window.setVisible(true);
window.setResizable(false);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
new Game();
}
});
}
#Override
public void changename(String name) {
System.out.println("I am clicked");
player1Str = new JLabel(name);
drawPanel.add(player1Str);
drawPanel.revalidate();
}
}
In the names class:
public class Names
{
private JLabel player1Label;
private JTextField player1Input;
private JButton nextButton;
public String nameString1;
public Names(){}
public Names(final Lawl game)
{
final JFrame window = new JFrame("Player 1 username");
JPanel firstPanel = new JPanel(new GridLayout(3,2));
player1Label = new JLabel("Player 1");
player1Input = new JTextField();
nextButton = new JButton("Next");
firstPanel.add(player1Label);
firstPanel.add(player1Input);
firstPanel.add(nextButton);
nextButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
nameString1 = player1Input.getText();
System.out.print(nameString1);
game.changename(nameString1);
// Names2 names2Call = new Names2();
window.dispose();
}
});
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.getContentPane().add(firstPanel);
window.setSize(250, 150);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}
How it works??
I created an interface and implemented it to the game class then pass the reference of the interface to the Names class which will then be called when button is clicked..
when it is called game.changename(nameString1);by the button clicked it will then be called on the game class as you could see there is an method from the implemented inteface in the game class that will be called when you click the button..
If you want to chain data dont create a new Main thread to just execute a new Window.. just use the one I did in the code..
replace
public final static JTextField player1Input;
instead of
private JTextField player1Input;
I want everytime i click on the button "bouton" to execute the function
boutonPane.Panel2(h, ....) which is supposed to display h circles. So i want 2 then 3 then 4, then 5... circles.
The problem is that it is not displaying the step with number 4. I see the function is called in the console but on the screen it does really 2, (press button) 3, (press button) 5, (press button)9. I dont see 4. I dont see 6,7,8.. Could you tell me what is the problem please? Here is the code:
public class Window extends JFrame implements ActionListener {
int lg = 1000; int lrg = 700;
int h = 2;
Panel b = new Panel();
private JButton btn = new JButton("Start");
JButton bouton = new JButton();
private JPanel container = new JPanel();
public Window(){
this.setTitle("Animation");
this.setSize(300, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
JPanel top = new JPanel();
btn.addActionListener(this);
top.add(btn);
container.add(top);
this.setContentPane(container);
this.setVisible(true);
}
public void Window2()
{
System.out.println("windows2");
this.setTitle("ADHD");
this.setSize(lg, lrg);
this.setLocationRelativeTo(null);
bouton.addActionListener(this);
if(h<11)
{
Panel boutonPane = new Panel();
boutonPane.Panel2(h, Color.BLUE ,lg, lrg, this.getGraphics());
System.out.println("draw"+h);
boutonPane.add(bouton);
this.add(boutonPane);
this.setContentPane(boutonPane);
this.revalidate();
this.repaint();
}
this.setVisible(true);
}
public void actionPerformed(ActionEvent e)
{
if((JButton)e.getSource()==btn)
{
System.out.println("pressed0");
Window2();
}
if((JButton)e.getSource()==bouton)
{
h++;
System.out.println("pressed"+h);
Window2();
}
}
}
Here is a the Panel class:
public class Panel extends JPanel
{
int m;
int i=1;
int a=0, b=0, tremp=0;
Color cc;
int lgi, lrgi;
int [] ta;
int [] tb;
Graphics gi;
int u=0;
Panel()
{
}
public void Panel2(int n, Color c, int lg, int lrg, Graphics g){
m=n;
cc=c;
gi=g;
lgi=lg;
lrgi=lrg;
ta = new int [n]; ta[0]=0;
tb = new int [n]; tb[0]=0;
}
public void paintComponent( final Graphics gr){
gr.setColor(Color.red);
for(int it=0; it<m;it++)
{
ta[it]=100*it;
tb[it]=100*it;
gr.fillOval(ta[it],tb[it], 150, 150);
}
}
}
"But would you have an idea of another, correct, way to do what I want please?"
You should only have one panel for the circles. There's absolutely no need to keep creating new panel.
Use a List for Ellipse2D objects. Just loop through them in the paintComponent method.
When you want to add a new circle, just add a new Ellipse2D object to the List and call repaint()
Here's an example.
NOTE Accept Gijs Overvliet's answer, as his was the one that answered your problem. I just wanted to share some insight.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class EllipseList extends JPanel {
private static final int D_W = 700;
private static final int D_H = 500;
private static final int CIRCLE_SIZE = 50;
private List<Ellipse2D> circles;
private double x = 0;
private double y = 0;
private CirclePanel circlePanel = new CirclePanel();
public EllipseList() {
circles = new ArrayList<>();
JButton jbtAdd = createButton();
JFrame frame = new JFrame();
frame.add(jbtAdd, BorderLayout.NORTH);
frame.add(circlePanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private JButton createButton() {
JButton button = new JButton("Add");
button.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e) {
circles.add(new Ellipse2D.Double(x, y, CIRCLE_SIZE, CIRCLE_SIZE));
x += CIRCLE_SIZE * 0.75;
y += CIRCLE_SIZE * 0.75;
circlePanel.repaint();
}
});
return button;
}
public class CirclePanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setPaint(Color.RED);
for (Ellipse2D circle : circles) {
g2.fill(circle);
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(D_W, D_H);
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new EllipseList();
}
});
}
}
Try this:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Window extends JFrame implements ActionListener
{
int lg = 1000;
int lrg = 700;
int h = 2;
Panel b = new Panel();
private JButton btn = new JButton("Start");
JButton bouton = new JButton();
private JPanel container = new JPanel();
Panel boutonPane = new Panel();
public Window()
{
this.setTitle("Animation");
this.setSize(300, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocationRelativeTo(null);
container.setBackground(Color.white);
container.setLayout(new BorderLayout());
JPanel top = new JPanel();
btn.addActionListener(this);
top.add(btn);
container.add(top);
this.setContentPane(container);
this.setVisible(true);
}
public void Window2()
{
System.out.println("windows2");
this.setTitle("ADHD");
this.setSize(lg, lrg);
this.setLocationRelativeTo(null);
bouton.addActionListener(this);
if (h < 11)
{
boutonPane.Panel2(h, Color.BLUE, lg, lrg, this.getGraphics());
System.out.println("draw" + h);
boutonPane.add(bouton);
this.add(boutonPane);
this.setContentPane(boutonPane);
updateWindow2();
}
this.setVisible(true);
}
public void updateWindow2()
{
boutonPane.Panel2(h, Color.BLUE, lg, lrg, this.getGraphics());
this.revalidate();
this.repaint();
}
public void actionPerformed(ActionEvent e)
{
if ((JButton) e.getSource() == btn)
{
System.out.println("pressed0");
Window2();
}
if ((JButton) e.getSource() == bouton)
{
h++;
System.out.println("pressed" + h);
updateWindow2();
}
}
public static void main(String[] args)
{
Test t = new Test();
}
}
What you did wrong was adding a new BoutonPane every time you clicked the button. The next time you clicked the button, you didn't click ONE button, but TWO buttons, adding two more boutonPanes, and two more buttons. This multiplies very quickly.
What I did was the following:
make boutonPane a class member variable
call window2() only once
create a method updateWindow2() for updating the circles. Call that method from window2() and actionPerformed().
So I have the following code, and whenever I press the square tool button it should draw a square in the lefthand corner, but I can't even get the console to print its message. That makes me think that the actionListener is never even responding to my click. Can anybody help?
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Game extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private GridPane gridPane;
private DragPanel drag;
public boolean isMouseClicked = false;
public static JMenuBar bar = new JMenuBar();
public int gridY = 1;
public int gridX = 1;
public int x = 0,y = 0;
public Game() {
setLayout(new BorderLayout());
OptionPanel options = new OptionPanel();
options.addActionListener(this);
add(options, BorderLayout.NORTH);
gridPane = new GridPane();
gridPane.setBorder(BorderFactory.createLineBorder(Color.white));
add(gridPane);
drag = new DragPanel();
drag.setBorder(BorderFactory.createLineBorder(Color.white));
drag.setBackground(new Color(100,100,125));
add(drag,BorderLayout.WEST);
}
public static void main(String args[]) {
Game game = new Game();
JFrame frame = new JFrame();
frame.setVisible(true);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setTitle("Game");
frame.setAlwaysOnTop(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(game);
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equalsIgnoreCase("grid")) {
gridPane.setGridOn(!gridPane.isGridOn());
}
if (e.getActionCommand().equalsIgnoreCase("square")){
gridPane.setSqaureOn(!gridPane.isSquareOn());
}
if (e.getActionCommand().equalsIgnoreCase("vgrid")){
gridPane.setVertOn(!gridPane.isVertOn());
}
}
public class GridPane extends JPanel {
private static final long serialVersionUID = 1L;
private boolean gridOn = false;
private boolean squareOn = false;
private boolean vertOn = false;
public GridPane() {
setBackground(Color.BLACK);
}
public boolean isGridOn() {
return gridOn;
}
public boolean isSquareOn(){
return squareOn;
}
public boolean isVertOn(){
return vertOn;
}
public void setGridOn(boolean value) {
if (value != gridOn) {
this.gridOn = value;
repaint();
}
}
public void setVertOn(boolean value){
if (value != vertOn){
this.vertOn = value;
repaint();
}
}
public void setSqaureOn(boolean value){
if (value != squareOn){
this.squareOn = value;
repaint();
}
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Toolkit tk = Toolkit.getDefaultToolkit();
if (gridOn) {
System.out.println("Grid works");
g.setColor(Color.white);
for (int i = 0; i < tk.getScreenSize().height; i += 64){
gridY++;
g.drawLine(0, (64 * gridY), tk.getScreenSize().width,(64 * gridY));
}
}
gridY = -1;
gridX = -1;
if (vertOn){
System.out.println("vert grid works");
g.setColor(Color.white);
for (int ig = 0; ig < tk.getScreenSize().width; ig += 64){
gridX++;
g.drawLine((64 * gridX), 0,(64 * gridX),tk.getScreenSize().height);
}
}
if (squareOn)
{
System.out.println("Square works");
g.setColor(Color.red);
g.fillRect(0,0,64,64);
}
}
}
public class DragPanel extends JPanel{
OptionPanel op = new OptionPanel();
public DragPanel(){
add(op.squareButton);
op.squareButton.setActionCommand("square");
}
public void addActionListener(ActionListener listener){
op.squareButton.addActionListener(listener);
}
}
public class OptionPanel extends JPanel {
public JButton grid;
public JButton vgrid;
public JButton squareButton;
public JTextField squareX;
public JTextField squareY;
public JTextField squareW;
public JTextField squareH;
public Square square = new Square();
public OptionPanel() {
//Sets the stuff for the panel
setBackground(new Color(155,0,255));
setLayout(new GridBagLayout());
//end
//The Show Grid Button Stuff
grid = new JButton("Show Horizontal Grid");
grid.setActionCommand("grid");
//end
//The vertical grid
vgrid = new JButton("Show Vertical Grid");
vgrid.setActionCommand("vgrid");
//end
//The Square tool button stuff
squareButton = new JButton("Sqaure Tool");
//end
squareX = new JTextField(3);
squareY = new JTextField(3);
squareW = new JTextField(3);
squareH = new JTextField(3);
//The gridbagConstraints things
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTH;
//kind of like padding
gbc.weighty = 1;
//sets the positions
gbc.gridx = 0;
gbc.gridy = 0;
//add it
add(grid, gbc);
//changes position for the second button
gbc.gridx = -1;
gbc.gridy = 0;
// adds it
add(vgrid,gbc);
//end
add(squareX,gbc);
add(squareY,gbc);
add(squareW,gbc);
add(squareH,gbc);
}
public void addActionListener(ActionListener listener) {
//adds action listeners
grid.addActionListener(listener);
vgrid.addActionListener(listener);
}
}
DragPanel had a different OptionPanel than the Game. I added the real one as a parameter and used this to qualify the reference, more to illustrate the problem than to suggest a correct usage. As HFOE suggests, re-factor your listeners to be as local as possible, using Action.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Game extends JPanel implements ActionListener {
private static final long serialVersionUID = 1L;
private GridPane gridPane;
private DragPanel drag;
public boolean isMouseClicked = false;
public static JMenuBar bar = new JMenuBar();
public int gridY = 1;
public int gridX = 1;
public int x = 0, y = 0;
public Game() {
setLayout(new BorderLayout());
OptionPanel options = new OptionPanel();
options.addActionListener(this);
add(options, BorderLayout.NORTH);
gridPane = new GridPane();
gridPane.setBorder(BorderFactory.createLineBorder(Color.white));
add(gridPane);
drag = new DragPanel(options);
drag.setBorder(BorderFactory.createLineBorder(Color.white));
drag.setBackground(new Color(100, 100, 125));
add(drag, BorderLayout.WEST);
}
public static void main(String args[]) {
Game game = new Game();
JFrame frame = new JFrame();
frame.setTitle("Game");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(game);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println(e);
if (e.getActionCommand().equalsIgnoreCase("grid")) {
gridPane.setGridOn(!gridPane.isGridOn());
}
if (e.getActionCommand().equalsIgnoreCase("square")) {
gridPane.setSqaureOn(!gridPane.isSquareOn());
}
if (e.getActionCommand().equalsIgnoreCase("vgrid")) {
gridPane.setVertOn(!gridPane.isVertOn());
}
}
public class GridPane extends JPanel {
private static final long serialVersionUID = 1L;
private boolean gridOn = false;
private boolean squareOn = false;
private boolean vertOn = false;
public GridPane() {
setBackground(Color.BLACK);
}
public boolean isGridOn() {
return gridOn;
}
public boolean isSquareOn() {
return squareOn;
}
public boolean isVertOn() {
return vertOn;
}
public void setGridOn(boolean value) {
if (value != gridOn) {
this.gridOn = value;
repaint();
}
}
public void setVertOn(boolean value) {
if (value != vertOn) {
this.vertOn = value;
repaint();
}
}
public void setSqaureOn(boolean value) {
if (value != squareOn) {
this.squareOn = value;
repaint();
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(320, 240);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Toolkit tk = Toolkit.getDefaultToolkit();
if (gridOn) {
System.out.println("Grid works");
g.setColor(Color.white);
for (int i = 0; i < tk.getScreenSize().height; i += 64) {
gridY++;
g.drawLine(0, (64 * gridY), tk.getScreenSize().width, (64 * gridY));
}
}
gridY = -1;
gridX = -1;
if (vertOn) {
System.out.println("vert grid works");
g.setColor(Color.white);
for (int ig = 0; ig < tk.getScreenSize().width; ig += 64) {
gridX++;
g.drawLine((64 * gridX), 0, (64 * gridX), tk.getScreenSize().height);
}
}
if (squareOn) {
System.out.println("Square works");
g.setColor(Color.red);
g.fillRect(0, 0, 64, 64);
}
}
}
public class DragPanel extends JPanel {
OptionPanel op;
public DragPanel(OptionPanel op) {
this.op = op;
this.add(this.op.squareButton);
this.op.squareButton.setActionCommand("square");
}
public void addActionListener(ActionListener listener) {
System.out.println(listener);
this.op.squareButton.addActionListener(listener);
}
}
private static class Square {
}
private class OptionPanel extends JPanel {
public JButton grid;
public JButton vgrid;
public JButton squareButton;
public JTextField squareX;
public JTextField squareY;
public JTextField squareW;
public JTextField squareH;
public Square square = new Square();
public OptionPanel() {
//Sets the stuff for the panel
setBackground(new Color(155, 0, 255));
setLayout(new GridBagLayout());
//end
//The Show Grid Button Stuff
grid = new JButton("Show Horizontal Grid");
grid.setActionCommand("grid");
//end
//The vertical grid
vgrid = new JButton("Show Vertical Grid");
vgrid.setActionCommand("vgrid");
//end
//The Square tool button stuff
squareButton = new JButton("Sqaure Tool");
//end
squareX = new JTextField(3);
squareY = new JTextField(3);
squareW = new JTextField(3);
squareH = new JTextField(3);
//The gridbagConstraints things
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.NORTH;
//kind of like padding
gbc.weighty = 1;
//sets the positions
gbc.gridx = 0;
gbc.gridy = 0;
//add it
add(grid, gbc);
//changes position for the second button
gbc.gridx = -1;
gbc.gridy = 0;
// adds it
add(vgrid, gbc);
//end
add(squareX, gbc);
add(squareY, gbc);
add(squareW, gbc);
add(squareH, gbc);
}
public void addActionListener(ActionListener listener) {
//adds action listeners
grid.addActionListener(listener);
vgrid.addActionListener(listener);
squareButton.addActionListener(listener);
System.out.println(listener);
}
}
}
I attempting to place a .jpg icon on top of a JPanel in order to represent a board piece on a board. I have a GUI folder with the .java files and another folder containing the .jpg files.
--Major Edit--
Example Code
When a square is clicked a white icon is meant to be placed then black etc etc. This is a very basic example of what im trying to achieve
import java.awt.Dimension;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class gui extends JFrame implements MouseListener {
/**
*
*/
private static final long serialVersionUID = -973341728129968945L;
JLayeredPane layeredPane;
JPanel board;
JLabel piece;
int numSquares;
private boolean currentPlayer;
public gui(){
Dimension boardSize = new Dimension(600, 600);
numSquares = 6;
currentPlayer = true;
layeredPane = new JLayeredPane();
getContentPane().add(layeredPane);
layeredPane.setPreferredSize(boardSize);
layeredPane.addMouseListener(this);
board = new JPanel();
layeredPane.add(board, JLayeredPane.DEFAULT_LAYER);
board.setLayout( new GridLayout(numSquares, numSquares) );
board.setPreferredSize( boardSize );
board.setBounds(0, 0, boardSize.width, boardSize.height);
for (int i = 0; i < (numSquares * numSquares); i++) {
JPanel square = new JPanel( new BorderLayout() );
square.setBorder(BorderFactory.createLineBorder(Color.black));
square.setBackground(Color.green);
board.add( square );
}
}
public static void main(String[] args) {
JFrame frame = new gui();
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE );
frame.pack();
frame.setResizable(true);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
#Override
public void mouseClicked(MouseEvent e) {
JPanel temp = (JPanel)board.findComponentAt(e.getX(), e.getY());
System.out.println(e.getX() + " " + e.getY());
if( currentPlayer ){
ImageIcon white = new ImageIcon("l/Images/white.jpg");
piece = new JLabel(white);
temp.add(piece);
}
else{
ImageIcon black = new ImageIcon( "/Images/black.jpg");
piece = new JLabel(black);
temp.add(piece);
}
currentPlayer = !currentPlayer;
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
}
}
Don't forget to revalidate and repaint if adding or removing components from a container. I've modified your SSCCE, and have gotten rid of the need to use images to make it runnable by folks who don't have access to your image files (like me!). Changes are noted by the // !! comments:
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
public class Gui2 extends JFrame implements MouseListener {
private static final long serialVersionUID = -973341728129968945L;
JLayeredPane layeredPane;
JPanel board;
JLabel piece;
int numSquares;
private boolean currentPlayer;
// !!
private ImageIcon whiteIcon;
private ImageIcon blackIcon;
public Gui2() {
// !!
whiteIcon = createIcon(Color.white);
blackIcon = createIcon(Color.black);
Dimension boardSize = new Dimension(600, 600);
numSquares = 6;
currentPlayer = true;
layeredPane = new JLayeredPane();
getContentPane().add(layeredPane);
layeredPane.setPreferredSize(boardSize);
layeredPane.addMouseListener(this);
board = new JPanel();
layeredPane.add(board, JLayeredPane.DEFAULT_LAYER);
board.setLayout(new GridLayout(numSquares, numSquares));
board.setPreferredSize(boardSize);
board.setBounds(0, 0, boardSize.width, boardSize.height);
for (int i = 0; i < (numSquares * numSquares); i++) {
// !! JPanel square = new JPanel(new BorderLayout());
JPanel square = new JPanel(new GridBagLayout()); // !!
square.setBorder(BorderFactory.createLineBorder(Color.black));
square.setBackground(Color.green);
square.setName(String.format("[%d, %d]", i % numSquares, i
/ numSquares)); // !!
board.add(square);
}
}
// !!
private ImageIcon createIcon(Color color) {
int width = 40;
int height = width;
BufferedImage img = new BufferedImage(width, height,
BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = img.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setColor(color);
g2.fillOval(0, 0, width, height);
g2.dispose();
ImageIcon icon = new ImageIcon(img);
return icon;
}
public static void main(String[] args) {
JFrame frame = new Gui2();
frame.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
frame.pack();
frame.setResizable(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#Override
// !!
public void mousePressed(MouseEvent e) {
JPanel temp = (JPanel) board.findComponentAt(e.getX(), e.getY());
System.out.println(e.getX() + " " + e.getY());
System.out.println(temp.getName()); // !!
if (currentPlayer) {
// !! ImageIcon white = new ImageIcon("l/Images/white.jpg");
// !! piece = new JLabel(white);
piece = new JLabel(whiteIcon); // !!
temp.add(piece);
} else {
// !! ImageIcon black = new ImageIcon("/Images/black.jpg");
// !! piece = new JLabel(black);
piece = new JLabel(blackIcon); // !!
temp.add(piece);
}
temp.revalidate(); // !!
temp.repaint(); // !!
currentPlayer = !currentPlayer;
}
#Override
public void mouseEntered(MouseEvent e) {
}
#Override
public void mouseExited(MouseEvent arg0) {
}
#Override
public void mouseClicked(MouseEvent arg0) {
}
#Override
public void mouseReleased(MouseEvent e) {
}
}
Also class names should be capitalized, and also you should again make your ImageIcons once. Again, one ImageIcon can be shared by many JLabels. You'll also want to respond to mousePressed not mouseClicked as mouseClicked can be fussy, especially if you move the mouse between press down and mouse release.
Hopefully you've also seen the value of an SSCCE. :)