0

I am working with Swing for the first time and am having a bit of an issue. What I have is a JFrame split into four JPanels. There is a MouseListener on the JFrame that acts like this

On a click, if the click is inside of the left hand bar, determine which of the 13 icons is being selected. If the click is inside the right hand "game pane" & an icon has been selected, place it at the location clicked.

This is done here

@Override
public void mouseClicked(MouseEvent event) {
    // TODO Auto-generated method stub
    xPos = event.getX();
    yPos = event.getY()-25;
    //If click is inside tool bar
    if(xPos<=75){
        if(yPos>-1 && yPos<48)
            //First tool image
              image = new ImageIcon(getClass().getResource(_image path_)).getImage();
        else if(yPos>=48 && yPos<96)
            //Second tool image
              image = new ImageIcon(getClass().getResource(_image path_)).getImage();
        else if(yPos>=96 && yPos<144)
            //Third tool image
              image = new ImageIcon(getClass().getResource(_image path_)).getImage();
        else if(yPos>=144 && yPos<192)
            //Fourth tool image
              image = new ImageIcon(getClass().getResource(imagepath)).getImage();
        else if(yPos>=192 && yPos<240)
            //Fifth tool image
              image = new ImageIcon(getClass().getResource(imagepath)).getImage();
        else if(yPos>=240 && yPos<288)
            //Sixth tool image
              image = new ImageIcon(getClass().getResource(imagepath)).getImage();
        else if(yPos>=288 && yPos<336)
            //Seventh tool image
              image = new ImageIcon(getClass().getResource(imagepath)).getImage();
        else if(yPos>=336 && yPos<384)
            //First NPC image
              image = new ImageIcon(getClass().getResource(imagepath)).getImage();
        else if(yPos>=384 && yPos<432)
            //second NPC image
              image = new ImageIcon(getClass().getResource(imagepath)).getImage();
        else if(yPos>=432 && yPos<480)
            //Third NPC image
              image = new ImageIcon(getClass().getResource(imagepath)).getImage();
        else if(yPos>=480 && yPos<528)
            //First Decoration image
              image = new ImageIcon(getClass().getResource(imagepath)).getImage();
        else if(yPos>=528 && yPos<576)
            //Second Decoration image
              image = new ImageIcon(getClass().getResource(imagepath)).getImage();
        else if(yPos>=576 && yPos<=625)
            //Third Decoration image
              image = new ImageIcon(getClass().getResource(imagepath)).getImage();
    }
    //If click is within Game Pane
    else if (xPos>75 && yPos<625){
        //A tool has been selected
        if(image!=null){
            placedTool = this.image;
            this.image = null;
            placeable = true;
        }
    }
    //An image and location on the game pane has been selected
    if(placeable && this.image==null){
        ImageInfo newImg = new ImageInfo(xPos, yPos, image);
        gamePane.additions.add(newImg);
        gamePane.repaint();
        System.out.println("IMAGE PLACED @ " + xPos + ", " + yPos);
        placeable = false;
    }

    System.out.println("CLICK: (" + xPos + "," + yPos +")");
}

Where imagepath is the path of a 50x50 icon. This portion works correctly with no errors. However gamePane doesn't get repainted properly.

gamePane simply has a background image for now. As components are added, they're supposed to be painted on top. All that gets painted is the background image though. Is there any way to specify the Z component using Graphics.drawImage(); Here's what I have for the paintComponent function of gamePane (bolded because this is the main issue)

@Override
protected void paintComponent(Graphics g) {
    g.drawImage(backgroundImg, 0, 0, null);
    for(ImageInfo add : additions){
        g.drawImage(add.getImage(), add.getX(), add.getY(), null);
    }
}

Where additions is defined like this

List additions = new ArrayList();

And the ImageInfo class just contains an image, an x coordinate, and a y coordinate

public class ImageInfo {
private int x;
private int y;
private Image image;

public int getX() {
    return x;
}

public int getY() {
    return y;
}

public Image getImage() {
    return image;
}

public ImageInfo(int x, int y, Image image) {
    super();
    this.x = x;
    this.y = y;
    this.image = image;
}

}

FIXED:

Thank you mKorbel. By defining all the images outside of the mouseClicked method

Image tool1 = new ImageIcon(getClass().getResource(toolBar.TOOL1)).getImage();
Image tool2 = new ImageIcon(getClass().getResource(toolBar.TOOL2)).getImage();
Image tool3 = new ImageIcon(getClass().getResource(toolBar.TOOL3)).getImage();
Image tool4 = new ImageIcon(getClass().getResource(toolBar.TOOL4)).getImage();
Image tool5 = new ImageIcon(getClass().getResource(toolBar.TOOL5)).getImage();
Image tool6 = new ImageIcon(getClass().getResource(toolBar.TOOL6)).getImage();
Image tool7 = new ImageIcon(getClass().getResource(toolBar.TOOL7)).getImage();
Image npc1 = new ImageIcon(getClass().getResource(toolBar.NPC1)).getImage();
Image npc2 = new ImageIcon(getClass().getResource(toolBar.NPC2)).getImage();
Image npc3 = new ImageIcon(getClass().getResource(toolBar.NPC3)).getImage();
Image decor1 = new ImageIcon(getClass().getResource(toolBar.DECOR1)).getImage();
Image decor2 = new ImageIcon(getClass().getResource(toolBar.DECOR2)).getImage();
Image decor3 = new ImageIcon(getClass().getResource(toolBar.DECOR3)).getImage();

and the executing the mouseClicked function like

@Override
public void mouseClicked(MouseEvent event) {
    // TODO Auto-generated method stub
    xPos = event.getX();
    yPos = event.getY()-25;
    //If click is inside tool bar
    if(xPos<=75){
        if(yPos>-1 && yPos<48)
            //First tool image
              image = tool1;
        else if(yPos>=48 && yPos<96)
            //Second tool image
              image = tool2;
        else if(yPos>=96 && yPos<144)
            //Third tool image
              image = tool3;
        else if(yPos>=144 && yPos<192)
            //Fourth tool image
              image = tool4;
        else if(yPos>=192 && yPos<240)
            //Fifth tool image
              image = tool5;
        else if(yPos>=240 && yPos<288)
            //Sixth tool image
              image = tool6;
        else if(yPos>=288 && yPos<336)
            //Seventh tool image
              image = tool7;
        else if(yPos>=336 && yPos<384)
            //First NPC image
              image = npc1;
        else if(yPos>=384 && yPos<432)
            //second NPC image
              image = npc2;
        else if(yPos>=432 && yPos<480)
            //Third NPC image
              image = npc3;
        else if(yPos>=480 && yPos<528)
            //First Yard Decoration image
              image = decor1;
        else if(yPos>=528 && yPos<576)
            //Second Yard Decoration image
              image = decor2;
        else if(yPos>=576 && yPos<=625)
            //Third Yard Decoration image
              image = decor3;
    }
    //If click is within Game Pane
    else if (xPos>75 && yPos<625){
        //A tool has been selected
        if(image!=null){
            placedTool = this.image;
            this.image = null;
            placeable = true;
        }
    }

    if(placeable && this.image==null){
        GamePiece newImg = new GamePiece(placedTool, xPos, yPos);
        gamePane.additions.add(newImg);
        gamePane.repaint();
        System.out.println("IMAGE PLACED @ " + xPos + ", " + yPos);
        placeable = false;
    }

    System.out.println("CLICK: (" + xPos + "," + yPos +")");
}

The images were added over top of the background image, by the previously given paintComponent method. They are a little off position, but still visible.

user2307421
  • 51
  • 1
  • 2
  • 6
  • possible duplicate of [Add image on mouse click? Java applet](http://stackoverflow.com/questions/32597653/add-image-on-mouse-click-java-applet) – Ram Sep 16 '15 at 19:58

3 Answers3

2

only a comments

  1. post an SSCCE short runnable, compilable

  2. why there is yPos = event.getY()-25; whats logics representing an integer at -25

  3. store all ImageIcons in local variable, store those ImageIcons in any array or List in the case that there is fixed logics instead of get coordinates and then load image = new ImageIcon(getClass().getResource( painted in paintComponent, do not provide any FileIO at runtime


  • create an grid of JLabels laid by GridLayout, add MouseListener to every JLabels, change an JLabel.setIcon(myImageIcon) from Mouse Event, rest of logics I'm missing without an SSCCE

for example

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.UIManager;

public class ChessBoard extends JFrame {

    private JFrame frame = new JFrame();
    private JPanel panel = new JPanel();
    private Icon errorIcon = UIManager.getIcon("OptionPane.errorIcon");
    private Icon infoIcon = UIManager.getIcon("OptionPane.informationIcon");
    private Icon warnIcon = UIManager.getIcon("OptionPane.warningIcon");
    private Icon questnIcon = UIManager.getIcon("OptionPane.questionIcon");
    private JButton button = new JButton("Reset my board");

    public ChessBoard() {
        panel.setLayout(new GridLayout(8, 8, 0, 0));
        for (int i = 0; i < 64; i++) {
            final JLabel label = new JLabel();
            label.setIcon(errorIcon);
            label.addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    if (e.getButton() == MouseEvent.BUTTON3) {
                        label.setIcon(infoIcon);
                    } else {
                        label.setIcon(warnIcon);
                    }
                }

                @Override
                public void mouseEntered(MouseEvent me) {
                    label.setIcon(questnIcon);
                }
            });
            panel.add(label);
        }
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                for (Component c : panel.getComponents()) {
                    if (c instanceof JLabel) {
                        JLabel label = (JLabel) c;
                        label.setIcon(errorIcon);
                    }
                }
            }
        });
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(panel);
        frame.add(button, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new ChessBoard();
            }
        });
    }
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • I am working on an SSCCE. But to answer the second point, I am not sure why but for the MouseListener all of the Y values were offset by 25. When I clicked the top most point of the window it gave 25 not 0, so I just subtracted this offset. – user2307421 Nov 04 '13 at 18:40
0

This looks suspicious:

if(placeable && this.image==null){

You do not declare image in the method, so it's the same as this.image, so the addition code is run only if image == null. Perhaps you meant:

if (placeable && this.image != null) {

(I do not know the purpose of placeable, so I left that as it was)

kiheru
  • 6,588
  • 25
  • 31
  • I don't think the image==null is really necessary since image is being set to null the same time placeable is being set to be true. I just did it out of precaution. Sorry it's slightly confusing. But the main issue is I can't repaint over the background image with the added images. – user2307421 Nov 04 '13 at 18:36
  • @user2307421 I mean the code results in *the images being never added* to `gamePane.additions`, because that's the condition on the block where the addition is done. – kiheru Nov 04 '13 at 20:06
0

Thanks to @MadProgrammer for this code, he helped me with this(meaning he did everything)

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.URL;

import javax.imageio.ImageIO;
import javax.sound.sampled.*;
import javax.swing.*;


import  sun.audio.*;

public class SHR {

    public static void main(String[] args) {
        new SHR();
    }

    public SHR() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("To Battle");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new ToBattle());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class ToBattle extends JPanel {

        private BufferedImage image;
        private Point drawPoint;

        public ToBattle() {
            try {
                image = ImageIO.read(getClass().getResource("SilverHandRecruit.png"));
                addMouseListener(new MouseAdapter() {

                    @Override
                    public void mouseClicked(MouseEvent e) {
                        drawPoint = new Point(e.getPoint());

                        repaint();
                    }

                });
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            if (drawPoint != null) {
                g2d.drawImage(image, drawPoint.x - 100, drawPoint.y - 100, this);
            }
            g2d.dispose();
        }

    }

}

You can check out the exact answer he posted here: Add image on mouse click? Java applet

Community
  • 1
  • 1
Roy Li
  • 3
  • 3