Search code examples
javaimageswingjbuttonmousehover

Mouse Hovering was Required for my Jbutton with pic to be visible


Mouse Hovering was Required for my Jbutton with pic to be visible, I didn't @Override my paint function anywhere.How to display all the buttons with images without the need of mouse hovering ?!

before Mouse hovering pic

After mouse hovering on all Jbuttons

public class JPicButton extends JButton {
int x, y, max;

/**
 * @param path
 *            :"resources/graphics/index.jpg"
 */
public JPicButton(String fileName, int max) {
    this.max = max;
    try {
        // ImageIcon mx = new ImageIcon(JPicButton.class.getResource("/graphics/" +
        // fileName)); #works
        Image img = ImageIO.read(JPicButton.class.getResource("/graphics/" + fileName));
        img = img.getScaledInstance(10 * (40 / max), 10 * (45 / max), Image.SCALE_SMOOTH);
        ImageIcon mc = new ImageIcon(img);
        this.setIcon(mc);
    } catch (Exception ex) {
        System.out.println(ex);
        ex.printStackTrace();
    }

}

public JPicButton() {

}

public void setOrigin(int x, int y) {
    this.x = x;
    this.y = y;
}

public void setPath(String fileName) {
    try {
        Image img = ImageIO.read(JPicButton.class.getResource("/graphics/" + fileName));
        img = img.getScaledInstance(10 * (40 / max), 10 * (45 / max), Image.SCALE_SMOOTH);
        ImageIcon mc = new ImageIcon(img);
        this.setIcon(mc);
    } catch (Exception ex) {
        System.out.println(ex);
        ex.printStackTrace();
    }
}

/**
 * @return the x
 */
public synchronized int getX() {
    return x;
}

/**
 * @return the y
 */
public synchronized int getY() {
    return y;
} }

this button is initialized in the constructor of the Jpanel too as

package Gui;

import javax.swing.JPanel;

 import javax.swing.JLabel;
 import javax.swing.SwingConstants;
 import java.awt.Font;
 import java.awt.Color;
 import javax.swing.JButton;
 import javax.swing.JFrame;

 @SuppressWarnings("serial")
 public class GamePage extends JPanel {
JPicButton groundMatrix[][];
int xMax, yMax;

public GamePage() {
    setBackground(Color.WHITE);
    setVisible(false);

    setLayout(null);
    setSize(700, 500);

    JLabel lblNewLabel = new JLabel("MineSweeper");
    lblNewLabel.setBounds(48, 13, 250, 50);
    add(lblNewLabel);
    lblNewLabel.setBackground(Color.PINK);
    lblNewLabel.setOpaque(true);
    lblNewLabel.setFont(new Font("Comic Sans MS", Font.PLAIN, 18));
    lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER);

    JPanel game = new JPanel();
    game.setBounds(50, 80, 600, 400);
    add(game);
    game.setLayout(null);

    JLabel lblNewLabel_1 = new JLabel("");
    lblNewLabel_1.setBounds(342, 15, 66, 50);
    add(lblNewLabel_1);

    JLabel label = new JLabel("");
    label.setBounds(584, 13, 66, 50);
    add(label);

    JButton btnNewButton = new JButton("Reset");
    btnNewButton.setBounds(446, 15, 97, 50);
    add(btnNewButton);

    xMax = 15;
    yMax = 10;
    int Width = 40;
    groundMatrix = new JPicButton[xMax][yMax];

    for (int y = 0; y < yMax; y++) {
        for (int x = 0; x < xMax; x++) {
            groundMatrix[x][y] = new JPicButton("Layout1d.jpg", 10);
            groundMatrix[x][y].setLocation(Width * x, Width * y);
            groundMatrix[x][y].setSize(Width, Width);
            game.add(groundMatrix[x][y]);
            groundMatrix[x][y].setOrigin(x, y);

        }

    }

    // GridBagConstraints mineGround = new GridBagConstraints();
    // mineGround.gridheight = 45;
    // mineGround.gridwidth = 40;

}

/**
 * @return the groundMatrix
 */
public synchronized JPicButton[][] getGroundMatrix() {
    return groundMatrix;
}

/**
 * @param groundMatrix
 *            the groundMatrix to set
 */
public synchronized void setGroundMatrix(JPicButton[][] groundMatrix) {
    this.groundMatrix = groundMatrix;
}

/**
 * @return the xMax
 */
public synchronized int getxMax() {
    return xMax;
}

/**
 * @return the yMax
 */
public synchronized int getyMax() {
    return yMax;
}

public static void main(String args[]) {
    JFrame js = new JFrame();
    GamePage gd = new GamePage();
    gd.setVisible(true);
    js.add(gd);
    js.pack();
    js.setSize(700, 500);
    js.setVisible(true);
}
}

for full code visit https://bitbucket.org/sarjuns/minesweeper/src


Solution

  • Observations (tl;dr)

    Having walked through your code, there are a number of issues which are likely compounding together to cause all sorts of issues, if not immediately, then into the future (and as the solution becomes more complex).

    Reliance of null layouts

    Every where I look in your code I see setLayout(null);. This is going to haunt you, especially as you try and run the code on different platforms

    Swing, like most decent UI frameworks, has an inbuilt concept of how components should be laid out in a platform independent manner.

    I'd highly recommend taking some time to look over Laying Out Components Within a Container

    Looking through your code I can find good places to use BorderLayout, GridBagLayout, GridLayout and CardLayout, all of which would greatly reduce the complexity of the code and make it easier to change (should you have to) and maintain, as well as support different platforms and rendering pipelines.

    Using the JLayeredPane of JFrame

    getLayeredPane().add(gamepage); ... I'm not sure what benefit you thought this was going to provide, but it's a very uncommon solution. The JLayeredPane is a great way to display "popup" style information to the user or provide "overlay" information over the content pane, but that's me.

    The core of the problem

    In the JPicButton class you implement two methods..

    /**
     * @return the x
     */
    public synchronized int getX() {
        return x;
    }
    
    /**
     * @return the y
     */
    public synchronized int getY() {
        return y;
    }
    

    The problem is, these two methods are already defined by JButton and relate to the location the button should be placed relative to it's parent container. Overriding these methods means that when you use setLocation, the values are been ignored.

    So, when I modify your code to remove those methods, I get the following result...

    Finally laid out

    The "x/y" position you are trying to manage should actually be managed by a model, the GUI should simply be a representation of the state of the model.

    Final Remarks

    I've made a number of remarks about the state of your code, it would unprofessional for me to do otherwise, as you are digging yourself into a never ending hole of re-work and head scratching issues which could be easily solved with the available API support.

    I believe, however, you've made a good start on attempting to solve the over all problem and would encourage you to continue, but taking into account some of the observations that have been made.