0

So Let's Start with a little bit of background. I am working on a Personal Project in JAVA mainly to experiment with the Java GUIs and, overall, learn more. The Project consists in Having A Menu GUI that is similar to that of a Videogame. For Example, The Main Menu has its buttons and Background image, but then when clicked on the options button, the options menu "Substitutes" the Main Menu, but not closing anything, changing the Background Image (Or at least having the possibility to do so) and the buttons and other components that may exist.

Now, that could be easily done by simply having all the JButton and JLabels and all that inside different JPanels and simply using setVisible(Boolean), the thing is, I also wanted to have an Actual Background image that would auto-scale itself as the user changes the size of the window for the menu, thus I couldn't use JLabels for the Image, and after searching I found a class with a special "JBackgroundPanel" (See Below) Which I have simplified a bit to fit my needs ( Mainly taking a couple methods out)

This is the JBackgroundPanel class (Original link is in the comment on top of public class JBackgroundPanel ... ):

import javax.swing.JPanel;
import java.awt.Image;
import javax.swing.JComponent;
import java.awt.Dimension;
import java.awt.BorderLayout;
import java.awt.Paint;
import java.awt.Rectangle;
import javax.swing.JScrollPane;
import javax.swing.JViewport;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;

/**
 * @author Rob Camick
 * @Date 12/10/2008
 * @Credits Here are the credits to the person that actually created this class.
 * {@code} http://www.camick.com/java/source/BackgroundPanel.java
 * {@link} https://tips4java.wordpress.com/2008/10/12/background-panel/
 * 
 *
 */

public class JBackgroundPanel extends JPanel    {

private Paint P;
private Image image;
private float xAlign = 0.5f;
private float yAlign = 0.5f;
private boolean isTransparentAdd = true;

public JBackgroundPanel(Image image)
{
    setImage(image);
    setLayout(new BorderLayout());
}

public JBackgroundPanel(Image image, float xAlign, float yAlign)
{
    setImage(image);
    setImageAlignX(xAlign);
    setImageAlignY(yAlign);
    setLayout(new BorderLayout());
}

public JBackgroundPanel(Paint P)
{
    setPaint( P);
    setLayout(new BorderLayout());
}

public void setImage(Image image)
{
    this.image = image;
    repaint();
}

public Image getImage(){

    return this.image;

}

public void setPaint(Paint P)
{
    this.P = P;
    repaint();
}

public void setImageAlignX(float xAlign)
{
    this.xAlign = xAlign > 1.0f ? 1.0f : xAlign < 0.0f ? 0.0f : xAlign;
    repaint();
}

public void setImageAlignY(float yAlign)
{
    this.yAlign = yAlign > 1.0f ? 1.0f : yAlign < 0.0f ? 0.0f : yAlign;
    repaint();
}

public void add(JComponent component)
{
    add(component, null);
}

public Dimension getPreferredSize()
{
    if (image == null)
        return super.getPreferredSize();
    else
        return new Dimension(image.getWidth(null), image.getHeight(null));
}

public void add(JComponent component, Object constraints)
{
    if (isTransparentAdd)
    {
        makeComponentTransparent(component);
    }

    super.add(component, constraints);
}

public void setTransparentAdd(boolean isTransparentAdd)
{
    this.isTransparentAdd = isTransparentAdd;
}

private void makeComponentTransparent(JComponent component)
{
    component.setOpaque( false );

    if (component instanceof JScrollPane)
    {
        JScrollPane scrollPane = (JScrollPane)component;
        JViewport viewport = scrollPane.getViewport();
        viewport.setOpaque( false );
        Component c = viewport.getView();

        if (c instanceof JComponent)
        {
            ((JComponent)c).setOpaque( false );
        }
    }
}

@Override
protected void paintComponent(Graphics g)
{
    super.paintComponent(g);


    if (P != null)
    {
        Dimension d = getSize();
        Graphics2D G = (Graphics2D) g;
        G.setPaint(P);
        G.fill( new Rectangle(0, 0, d.width, d.height) );
    }

    if (image == null ) return;

    draw(g);


}

private void draw(Graphics g)
    {
        Dimension d = getSize();
        g.drawImage(image, 0, 0, d.width, d.height, null);
    }





}

This Code works perfectly fine. Now, I think you should also have my code. See Below:

import java.awt.Container;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.imageio.ImageIO;
import JBackgroundPanel;
import javax.swing.JFrame;
import javax.swing.JPanel;



public class MainUI extends JFrame implements /*ActionListener*/    {

private Container cont = this.getContentPane();
private JBackgroundPanel bgPanel;
private Image bgImg;


private enum GState{

    GMenuOne,
    GMenuTwo,

};

private GState MENU_STATE = GState.GMenuOne;

public MainUI() {

    this.setPreferredSize(this.getMaximumSize());
    this.setResizable(true);
    this.setSize(this.getMaximumSize());
    this.setUndecorated(false);
    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
    this.initComponents();
    this.reload();
    this.setVisible(true);

    this.MENU_STATE = GState.GMenuOne;
    this.reload();

}

public void reload()    {

    if(this.MENU_STATE.equals(GState.GMenuOne) )    {

        this.loadBackground("MenuOne"/*LOAD MAIN MENU*/);
        this.repaint();

    }   else if(this.MENU_STATE.equals(GState.GMenuTwo))    {

        this.loadBackground("MenuTwo");
        repaint();

        }   

    }

public boolean loadBackground(String Bg)     {

    try {


            bgImg = ImageIO.read(new File("src/resImg/" + Bg + ".png"));
            bgPanel = new JBackgroundPanel(bgImg, 1.0f, 0.5f);
            System.out.println("Image Was Successfully Loaded");


        return true;

    }catch(Exception ex) {

        System.out.println("IMAGE WITH ID " + Bg + " COULD NOT BE FOUND");
        ex.printStackTrace();
        return false;


    }

}


private void initComponents()   {

    this.reload();
    this.add(bgPanel);


}



}

Now you have all the background information I can provide, let's get to the point.

I know that if I create new JBackgroundPanels or possibly even by just calling this.loadBackground("IMAGE"); (And Adding in the end this.add(bgPanel); , As to my understanding a new instance of bgPanel is being created, so it hasn't been added to the GUI yet) it will show the next image everytime we call the this.reload() method after changing the STATE.

So My Question is: Wouldn't it be better / more optimal To just change the image somehow, without creating new Instances of the JBackgroundPanel? If it is, or isn't, please, explain (So I can understand what's wrong or right with my logic, because to me that is what would make most sense), and how would you go about doing this? (Even if it isn't the most optimal way of doing it)

Running Class Can be seen here:

public class RunningClass {

public static void main(String[] argv)  {


    MainUI ui = new MainUI();


}

}

Thanks A lot!

Kiwii
  • 29
  • 5
  • 1
    *"Also the run class is not included, but I don't think there's the need to do so as it is just initializing the object."* 1) For better help sooner, post a [MCVE] or [Short, Self Contained, Correct Example](http://www.sscce.org/). 2) One way to get image(s) for an example is to hot link to images seen in [this Q&A](http://stackoverflow.com/q/19209650/418556). – Andrew Thompson Aug 04 '16 at 17:41
  • BTW - yes it would be best (IMO) to have a method that allows the programmer to set a new BG image, but if the components are changing as well, I'd use a [`CardLayout`](http://download.oracle.com/javase/8/docs/api/java/awt/CardLayout.html) (using two panels as the main views) as shown in [this answer](http://stackoverflow.com/a/5786005/418556). – Andrew Thompson Aug 04 '16 at 17:42
  • `bgImg = ImageIO.read(new File("src/resImg/" + Bg + ".png"));` Application resources will become embedded resources by the time of deployment, so it is wise to start accessing them as if they were, right now. An [tag:embedded-resource] must be accessed by URL rather than file. See the [info. page for embedded resource](http://stackoverflow.com/tags/embedded-resource/info) for how to form the URL. – Andrew Thompson Aug 04 '16 at 17:44
  • @AndrewThompson I just added the RunningClass to the code itself. I see what you mean by Using URL instead of file. That makes sense. Thanks for that. Also, in the case we had to write that "Change only the Image" Method without initializing another JBackgroundPanel by doing `bgPanel = new JBackgroundPanel(...)`, How would you go about it? (Assumming only an image would be changed, which isn't What i'm going for) I'll try using a CardLayout and see if it indeed fits my needs (As I want it to ) – Kiwii Aug 04 '16 at 17:57
  • 1
    Note that I did not advise you to post the runner code, but an MCVE. Please follow the link and read it. – Andrew Thompson Aug 04 '16 at 18:08

0 Answers0