How to add a graphical user interface separate from the game canvas in Java?

Started by
4 comments, last by Nicholas Kong 11 years, 2 months ago

So I am faced with a situation that I have been stuck with for an hour.

Here's my situation: I want to add an image that says "Life:" separate from my game canvas very much like this game Legend of Zelda for the NES.

Problem is: my code still only shows my game canvas.

public class Game extends Canvas {
private Game(){
JFrame container = new JFrame("Arcade Shooter Clone");
panel = (JPanel)container.getContentPane();
panel.setLayout(new BorderLayout());
panel.add(this,BorderLayout.CENTER);
ShipLifeTitle shipLifeTitle = new ShipLifeTitle();
panel.add(shipLifeTitle,BorderLayout.SOUTH);
}
}
public class ShipLifeTitle extends Sprite {
private Image image;
public ShipLifeTitle()
{
try
{
image = ImageIO.read(new File("src/Ship/shipLifeTitle.PNG"));
}
catch(IOException e)
{
e.printStackTrace();
}
}
@Override
public void draw(Graphics g) {
// TODO Auto-generated method stub
g.drawImage(image, 200, 200, null);
}
}
public class Sprite extends Component implements GameComponent {
public Vector2D position;
public Vector2D velocity;
@Override
public void update(long milliseconds) {
// TODO Auto-generated method stub
}
@Override
public void draw(Graphics g) {
// TODO Auto-generated method stub
}
}

Advertisement

It's possible that the problem lies with BorderLayout. BorderLayout gives priority to the center, and BorderLayout often ignores default size values. The first thing I would try would be to explicitly set the preferred size of your shipLifeTitle. Then hopefully the BorderLayout will use the size that you set to it. Otherwise, you may consider using a different layout manager. I really enjoy BoxLayout.

Note, I'm not by any means a pro at setting layouts. However, in my java class last semester I really wanted to try and get a handle on them. If I can manage to insert code correctly in the post here, I'll try to include a code sample from a similar problem that I solved using BorderLayout.

This assignment used an Applet, but I believe the panels work the same. I've never used canvas, though, so there may be something going on there that I'm not aware of.

Hope this helps, good luck.


//Applet for Exercise 23.9, Draw Rectangle

import javax.swing.JApplet;
import java.awt.BorderLayout;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class DrawRectangle extends JApplet
{
     //structural panels and controls
     private DrawPanel drawPanel;
     private JPanel inputPanel;
     private JLabel left;
     private JLabel top;
     private JLabel width;
     private JLabel height;
     private JTextField leftField;
     private JTextField topField;
     private JTextField widthField;
     private JTextField heightField;
     private JButton drawIt;

     //panel dimensions
     private Dimension inputDim = new Dimension(300, 60);
     private Dimension drawDim = new Dimension(300, 300);

     //inputs for the rectancle to be drawn
     private String leftString;
     private String topString;
     private String widthString;
     private String heightString;
     private int leftInt;
     private int topInt;
     private int widthInt;
     private int heightInt;

   public void init()
   {
      drawPanel = new DrawPanel();
      drawPanel.setPreferredSize( drawDim );
      add(drawPanel);
      inputPanel = new JPanel();
      inputPanel.setPreferredSize( inputDim );
      add(inputPanel, BorderLayout.SOUTH);

      left = new JLabel("Left: ");
      inputPanel.add(left);    

      leftField = new JTextField( 2 );
      inputPanel.add(leftField);

      top = new JLabel( "Top: " );
      inputPanel.add(top);

      topField = new JTextField( 2 );
      inputPanel.add(topField);

      width = new JLabel( "Width: " );
      inputPanel.add(width);

      widthField = new JTextField( 2 );
      inputPanel.add(widthField);

      height = new JLabel( "Height: " );
      inputPanel.add(height);

      heightField = new JTextField( 2 );
      inputPanel.add(heightField);

      drawIt = new JButton( "Draw It" );
      inputPanel.add(drawIt);

      //On Button Press, sends textfield data to rectangle setters and calls repaint for the drawPanel
      drawIt.addActionListener(
         new ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               leftString = new String( leftField.getText() );
               leftInt = Integer.parseInt( leftString );
               drawPanel.setLeft( leftInt );

               topString = new String( topField.getText() );
               topInt = Integer.parseInt( topString );
               drawPanel.setTop( topInt );

               widthString = new String( widthField.getText() );
               widthInt = Integer.parseInt( widthString );
               drawPanel.setWide( widthInt );

               heightString = new String( heightField.getText() );
               heightInt = Integer.parseInt( heightString );
               drawPanel.setTall( heightInt );

               drawPanel.repaint();
            }
         }//end ActionListener class
      );

   }//end init

}//end DrawRectangle

class DrawPanel extends JPanel
{
   private int left;
   private int top;
   private int wide;
   private int tall;

   public void setLeft( int l )
   {
      left = l;
   }
   public int getLeft()
   {
      return left;
   }

   public void setTop( int t )
   {
      top = t;
   }
   public int getTop()
   {
      return top;
   }

   public void setWide( int w )
   {
      wide = w;
   }
   public int getWide()
   {
      return wide;
   }

   public void setTall( int h )
   {
      tall = h;
   }
   public int getTall()
   {
      return tall;
   }


   public void paintComponent( Graphics g )
   {
      super.paintComponent( g );
      g.drawRect( getLeft(), getTop(), getWide(), getTall() );
   }//end paintComponent
}//end DrawPanel

It's possible that the problem lies with BorderLayout. BorderLayout gives priority to the center, and BorderLayout often ignores default size values. The first thing I would try would be to explicitly set the preferred size of your shipLifeTitle. Then hopefully the BorderLayout will use the size that you set to it. Otherwise, you may consider using a different layout manager. I really enjoy BoxLayout.

Note, I'm not by any means a pro at setting layouts. However, in my java class last semester I really wanted to try and get a handle on them. If I can manage to insert code correctly in the post here, I'll try to include a code sample from a similar problem that I solved using BorderLayout.

This assignment used an Applet, but I believe the panels work the same. I've never used canvas, though, so there may be something going on there that I'm not aware of.

Hope this helps, good luck.


//Applet for Exercise 23.9, Draw Rectangle

import javax.swing.JApplet;
import java.awt.BorderLayout;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JButton;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class DrawRectangle extends JApplet
{
     //structural panels and controls
     private DrawPanel drawPanel;
     private JPanel inputPanel;
     private JLabel left;
     private JLabel top;
     private JLabel width;
     private JLabel height;
     private JTextField leftField;
     private JTextField topField;
     private JTextField widthField;
     private JTextField heightField;
     private JButton drawIt;

     //panel dimensions
     private Dimension inputDim = new Dimension(300, 60);
     private Dimension drawDim = new Dimension(300, 300);

     //inputs for the rectancle to be drawn
     private String leftString;
     private String topString;
     private String widthString;
     private String heightString;
     private int leftInt;
     private int topInt;
     private int widthInt;
     private int heightInt;

   public void init()
   {
      drawPanel = new DrawPanel();
      drawPanel.setPreferredSize( drawDim );
      add(drawPanel);
      inputPanel = new JPanel();
      inputPanel.setPreferredSize( inputDim );
      add(inputPanel, BorderLayout.SOUTH);

      left = new JLabel("Left: ");
      inputPanel.add(left);    

      leftField = new JTextField( 2 );
      inputPanel.add(leftField);

      top = new JLabel( "Top: " );
      inputPanel.add(top);

      topField = new JTextField( 2 );
      inputPanel.add(topField);

      width = new JLabel( "Width: " );
      inputPanel.add(width);

      widthField = new JTextField( 2 );
      inputPanel.add(widthField);

      height = new JLabel( "Height: " );
      inputPanel.add(height);

      heightField = new JTextField( 2 );
      inputPanel.add(heightField);

      drawIt = new JButton( "Draw It" );
      inputPanel.add(drawIt);

      //On Button Press, sends textfield data to rectangle setters and calls repaint for the drawPanel
      drawIt.addActionListener(
         new ActionListener()
         {
            public void actionPerformed(ActionEvent e)
            {
               leftString = new String( leftField.getText() );
               leftInt = Integer.parseInt( leftString );
               drawPanel.setLeft( leftInt );

               topString = new String( topField.getText() );
               topInt = Integer.parseInt( topString );
               drawPanel.setTop( topInt );

               widthString = new String( widthField.getText() );
               widthInt = Integer.parseInt( widthString );
               drawPanel.setWide( widthInt );

               heightString = new String( heightField.getText() );
               heightInt = Integer.parseInt( heightString );
               drawPanel.setTall( heightInt );

               drawPanel.repaint();
            }
         }//end ActionListener class
      );

   }//end init

}//end DrawRectangle

class DrawPanel extends JPanel
{
   private int left;
   private int top;
   private int wide;
   private int tall;

   public void setLeft( int l )
   {
      left = l;
   }
   public int getLeft()
   {
      return left;
   }

   public void setTop( int t )
   {
      top = t;
   }
   public int getTop()
   {
      return top;
   }

   public void setWide( int w )
   {
      wide = w;
   }
   public int getWide()
   {
      return wide;
   }

   public void setTall( int h )
   {
      tall = h;
   }
   public int getTall()
   {
      return tall;
   }


   public void paintComponent( Graphics g )
   {
      super.paintComponent( g );
      g.drawRect( getLeft(), getTop(), getWide(), getTall() );
   }//end paintComponent
}//end DrawPanel

I added this in my Game constructor:

ShipLifeTitle shipLifeTitle = new ShipLifeTitle();

shipLifeTitle.setPreferredSize(new Dimension(shipLifeTitle.getImage().getWidth(null),shipLifeTitle.getImage().getHeight(null)));
panel.add(shipLifeTitle,BorderLayout.SOUTH);
I added this overridden method in my ShipLifeTitle class:
public void setPreferredSize(Dimension dimension)
{
width = dimension.width;
height = dimension.height;
}
My result of this modification is this. It is a grayed out portion being added to the south. My canvas and ship got messed up too now. This is a weird problem. blink.png
javaproblem_zps2e5ed5d2.jpg

I see the problem. Since my ShipLifeTitle object is not being added to the canvas, I need to use Swing's painting method

Ah, interesting. I didn't even consider the need for paint there. Thanks for posting what you came up with, I'm sure it will help me in the future.

Cheers.

Ah, interesting. I didn't even consider the need for paint there. Thanks for posting what you came up with, I'm sure it will help me in the future.

Cheers.

No prob. I'm sure it would help the next person too ,who happen to be reading this post.

This topic is closed to new replies.

Advertisement