1

Been having fun transitioning through a variety of layouts/nulls and other methods in an attempt to get my background image to fit my frame perfectly without annoying gaps which I have so far been unable to clear. Every attempt has either led to larger gaps. if the layout was set to left, the image inevitably fills gaps on the left but widen's the ones on the right and the last attempt by adding the image to the frame directly filled it perfectly, but led to the other elements on screen no longer receiving the repaint calls

enter image description here

At the moment my game sets up a jframe, creates my game system class which extends JPanel, and the game system class creates inner classes which handle either the start screen or actual game screen elements. Inside the game container class which is created by the System is where the background is being painted.

Shortened down code extract

Main Class:

    public class Test extends JPanel {

////////////////
////Variables //
////////////////////////////
/**/private static Test test;
/**/private static JFrame stage;
/**/private static Container CurrentMenu;
/**/private boolean isRunning = true; //used to state whether game is running
////////////////////////////////////

////////////////
// initialize //
////////////////
/**/public static void main(String[] args) {
/**/stage = new JFrame("Touhou FBE");//creates game window
/**/stage.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//sets up default handler for closing window
/**/test = new Test();//creates an object of our game
/**/stage.getContentPane().add(test);//add game object to frame 
/**/stage.pack();
/**/stage.setVisible(true);//sets frame to visible
/**/stage.setResizable(false);
/**/test.Game_loop();
/**/}
////////////////////////////

/////////////////
// constructor //
/////////////////
/**/public Test(){
/**////////////////////////////////
/**/// create starting game menu //
/**////////////////////////////////          //////////////////
/**/CurrentMenu = new Container(this,stage);     // swap GameMenu with GameContainer to be able to see difference with painting
/**/this.add(CurrentMenu);                   //////////////////
/**/}
///////////////////////


    ////////////////////////////////////////////
    // Game loop which manages object updates //
    ////////////////////////////////////////////
    /**/public void Game_loop(){
    /**/while (isRunning) {
    /**/test.repaint();
    /**/}
    /**/}
    /////////////////////////////////////////////////

    /////////////////////////////////
    // Rendering canvas for images //
    /////////////////////////////////
    /**/public void paint(Graphics g) {
    /**/super.paint(g); //Refresh Panel
    /**/}
    /////////////////////////////////////////////////////// 

Container Class:

    //////////////////////////
// game container class //
//////////////////////////
/**/public class Container extends JPanel{
/**/    
///////////////
//Variables //
///////////////
/**/public Test Game; 
/**/public JFrame stage; 
/**/private Image img;  

////////////////
//Constructor //
////////////////
/**/public Container(Test game, JFrame Stage){
/**/Game = game;
/**/stage = Stage;  
/**/img = (new ImageIcon("resources/background.png").getImage());
/**/Dimension size = new Dimension(700, 400);
/**/setPreferredSize(size);
/**/setMinimumSize(size);
/**/setMaximumSize(size);
/**/setLayout(null);
/**/setSize(size);
/**/}
/**/    
////////////////////////////

//////////////////
//Paint sprite //
//////////////////
/**/public void paintComponent(Graphics g) {
/**///super.paint(g);
/**/g.drawImage(img, 0,0, this);
/**/}
////////////////////////////////////
}

Image used in program and example (Rename to background) enter image description here http://img716.imageshack.us/img716/6410/seq6.png

At the moment I've reached the point where if I Have to, I would leave the gap in as it doesn't effect the overall game, however it's bugging me so bad and every attempt at swapping layouts, removing hgap/vgap, forcing the location of the image or following tutorials has led to no real change. Help would be greatly appreciated and will help make sure I never come across issues like this again.

ulthanex
  • 47
  • 7
  • 1) For better help sooner, post an [SSCCE](http://sscce.org/). 2) One way to get image(s) for an example is to hot-link to the images seen in [this answer](http://stackoverflow.com/a/19209651/418556). – Andrew Thompson Dec 23 '13 at 18:53
  • I love the way you are organizing your code with //// and /**/ – Yehia Awad Dec 23 '13 at 18:55
  • I presumed that the two classes made up a SSCCE as it is effectively the bare bones of the code which is affected, still got to learn how to make a more effective SSCCE. Also I guess with the image, it would help if I linked the original background image is what you are asking. – ulthanex Dec 23 '13 at 19:05
  • I have not read through your code, so I may be off key here... Can't you just `pack()` your `JFrame`? – PM 77-1 Dec 23 '13 at 19:22
  • within the code I used stage as a reference to the JFrame which I have used the pack() method on, however these gaps are what still remain afterwords, one thing I read on another post was that pack() apparently leaves a 5px gap/border as default? not entirely sure if thats the issue though. – ulthanex Dec 23 '13 at 19:29
  • @ulthanex *"still got to learn how to make a more effective SSCCE"* No, an SSCCE is either an SSCCE or not an SSCCE. There is no room for compromise. That is **not** an SSCCE because it has two source files, and requires an image. The problem of source files can be handled by reducing the visibility of the 2nd class to default, and the image can be obtained by ***hot-linking to one.*** – Andrew Thompson Dec 23 '13 at 19:38

1 Answers1

2

Calling setResizable changes the size of the frame.

Instead, try calling setResizable first, then pack, the setVisible

For example...

Updated

The continuing "padding" is caused by the fact that Test extends from JPanel and Container is added to it.

The default layout manager for JPanel is FlowLayout, which, by default, adds 5 pixels by default all around the container.

Depending on your needs, I would either change the layout manager for Test to BorderLayout or simply add Container directly to the frame (which uses a BorderLayout by default)

For example...

enter image description here

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestResize {

    private JFrame stage;
    private Container CurrentMenu;
    private boolean isRunning = true; //used to state whether game is running

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestResize();
            }
        });
    }

    public TestResize() {
        CurrentMenu = new Container(this, stage);     // swap GameMenu with GameContainer to be able to see difference with painting
        stage = new JFrame("Touhou FBE");//creates game window
        stage.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//sets up default handler for closing window
        stage.add(CurrentMenu);
        stage.setResizable(false);
        stage.pack();
        stage.setVisible(true);//sets frame to visible
        // This needs to be started in a separate thread
//        test.Game_loop();
    }

    public void Game_loop() {
//        while (isRunning) {
//            test.repaint();
//        }
    }

    public class Container extends JPanel {

        public TestResize Game;
        public JFrame stage;
        private Image img;

        public Container(TestResize game, JFrame Stage) {
            Game = game;
            stage = Stage;
            img = (new ImageIcon("resources/background.png").getImage());
        }

        @Override
        public Dimension getPreferredSize() {
            Dimension size = img == null ? new Dimension(700, 400) : new Dimension(img.getWidth(this), img.getHeight(this));
            return size;
        }

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawImage(img, 0, 0, this);
            g.setColor(Color.RED);
            g.drawRect(0, 0, getWidth() - 1, getHeight() - 1);            
        }
    }
}
Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • +1, you seem to be right. At least in the case of my couple test runs of different apps – Paul Samsotha Dec 23 '13 at 19:44
  • As you mentioned above and in this question, by changing the order of the setResizable method the left/right and bottom gaps are now filled, however the 4-5px gap above is still there. One thing I found though through using the getters, effectively the image is being drawn at (0,0) so for whatever reason, the actual class on the JFrame is being shunted down by 5px's, something to do with the layout? – ulthanex Dec 23 '13 at 19:44
  • You're missing a portion of your code (Test) so it's impossible to be sure. It could be that there's a Border or of the preferred size of the Test is larger then the image. I don't know why you've overridden paint as it's not doing anything, and you should be calling super.paintComponent to ensure that graphics context is properly prepared before painting to it... – MadProgrammer Dec 23 '13 at 20:00
  • The only difference between this test code and my actual project in the case of affecting the frame was that i had forgotten that i had called Dimension getPreferredSize() to set the dimensions of it to 700,400 the same size as the picture. Other then that i have set no borders, unless there are default, uncommented the super.paintcomponent, originally it was painting the image twice in slight overlap, now it doesnt. – ulthanex Dec 23 '13 at 20:16
  • Just tried drawing a simple square in the test class at (0,0), drew correctly in the top left corner, so for whatever reason which i will find out, when the container class is added to the JFrame, it's being moved down by 5px, therefore when the background image is being drawn at (0,0) effectively its actually being drawn at (0,5) – ulthanex Dec 23 '13 at 20:37
  • Watching Pepper Pig with my daughter, so I can't test your code, need to wait for wife to grace us with her presence (sleeping in) – MadProgrammer Dec 23 '13 at 20:41
  • *"uncommented the super.paintcomponent, originally it was painting the image twice in slight overlap"* This is because you were calling `super.paint` from within `paintComponent` - or at least it would have created a `StackOverflowError`... – MadProgrammer Dec 23 '13 at 22:37