This question already has an answer here:
Creating a space for Graphics2D drawings
(1 answer)
Closed 8 years ago.
I am trying to make a simple game in Java. I set a size of my frame in this way:
getContentPane().setPreferredSize(new Dimension(1280, 720));
And then I added a JComponent object, which draws whole graphics in my game:
getContentPane().add(gameGraphics);
And it all seemed to work properly, till I tried to prevent game objects from going out-of-map. "Game engine" teleports every object that went below 0 or above 720 in height or 1280 in width. I am sure that algorithm works perfectly (I checked it very precisely) and just look what happens when I try to reach lower-right corner of the window (while upper-left works properly!):
(A player is that blue rectangle in a corner)
There is a 10-pixel line of free space on the right and down of the window. So a content of the window must be bigger than 1280x720 pixels.
Do you have any ideas what is wrong here? Thanks.
There is a whole JFrame code:
MainFrame() {
super("GameOne");
setLayout(new BorderLayout());
getContentPane().setPreferredSize(new Dimension(RES_WIDTH, RES_HEIGHT));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
gameGraphics = new GameGraphics();
getContentPane().add(gameGraphics);
new Player();
new TestShip(10, 10);
pack();
setLocationRelativeTo(null);
setResizable(false);
setVisible(true);
}
GameGraphics as I said is a class that extends JComponent and everything which can be seen in the game is generated in a paintComponent method of this class.
RES_WIDTH and RES_HEIGHT are constants that are equal to 1280 and 720 respectively.
PROBLEM SOLVED:
A solution is to override a JComponent class's getPreferredSize() method (in my application it will be in GameGraphics class) (many layout managers ask every component for that and pack() method also does it). You just need to make it return a size (in 'Dimension') you want it to have.
Also it's probably better to make a JFrame 'setResizable(false)' before you call pack().
PROBLEM SOLVED:
A solution is to override a JComponent class's getPreferredSize() method (in my application it will be in GameGraphics class) (many layout managers ask every component for that and pack() method also does it). You just need to make it return a size (in 'Dimension') you want it to have. Also it's probably better to make a JFrame 'setResizable(false)' before you call pack().
Related
I'm a somewhat novice programmer and I'm have some trouble adding an image to my frame. While I know how to add images generally, this specific case it does not work.
public class Tutorial extends JFrame{
Tutorial(){
JFrame frame = new JFrame("ImageTutorial");
frame.setVisible(true);
frame.setSize(750,850);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(null);
ImageIcon image = new ImageIcon(getClass().getResource("Green Block.png"));
JLabel imagelabel = new JLabel(image);
imagelabel.setBounds(10, 10, 75, 75);
imagelabel.setOpaque(true);
frame.add(imagelabel);
Now, I've located the problem but I don't understand 'why' its a problem. When I remove
frame.setSize(750,850);
the image shows, but when its there it doesn't. How can the frame's size impact the image showing and how can I get around it?
Just curious, logically, what makes you think a frame should be visible before you add any components? Logically speaking, wouldn't it seem right to add your components first, then make the frame visible. It's like displaying a painting in an art gallery even before the painter has painted anything on it. It just makes no sense. I highly doubt setting the size has anything to do with it. IF you don't set the size of the frame, then the frame appears as small as possible. When you resize the frame, it causes a repaint, then showing the label you add. But generally, you want to always set frame visible after all you components are added, to avoid this problem.
Side note: You should stay away from null layouts. You need to learn to use Layout Managers and let them do the dynamic sizing and locating for you.
This question has been asked a lot but everywhere the answers fall short. I can get a JFrame to display a background image just fine by extending JPanel and overriding paintComponent, like so:
class BackgroundPanel extends JPanel {
private ImageIcon imageIcon;
public BackgroundPanel() {
this.imageIcon = Icons.getIcon("foo");
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(imageIcon.getImage(), 0,0,imageIcon.getIconWidth(),imageIcon.getIconHeight(),this);
}
}
But now, how do you add a component on top of that background?
When I go
JFrame w = new JFrame() ;
Container cp = w.getContentPane();
cp.setLayout(null);
BackgroundPanel bg = new BackgroundPanel();
cp.add(bg);
JPanel b = new JPanel();
b.setSize(new Dimension(30, 40));
b.setBackground(Color.red);
cp.add(b);
w.pack()
w.setVisible(true)
It shows the little red square (or any other component) and not the background, but when I remove cp.setLayout(null);, the background shows up but not my other component. I'm guessing this has something to do with the paintComponent not being called by the null LayoutManager, but I'm not at all familiar with how LayoutManagers work (this is a project for college and the assignment specifically says not to use a LayoutManager).
When i make the image the background has to display null (and so, transparant (??)) the red square shows up so it might be that the background is actually above my other components.
Does anyone anyone have any ideas?
Thanks
When using null layout (and you almost never should) you have to supply a bounds for every component, otherwise it defaults to (0 x,0 y,0 width,0 height) and the component won't display.
BackgroundPanel bg = new BackgroundPanel();
cp.add(bg);
isn't supplying a bounds. You'll need to do something like:
BackgroundPanel bg = new BackgroundPanel();
bg.setBounds(100, 100, 100, 100);
cp.add(bg);
Which would make bg size 100 x 100 and place it at 100 x, 100 y on the frame.
Look in the documentation on the Root Pane for all the information you need. Note the availability of the layered pane and the glass pane as well as the content pane.
By default all components have a 0 size. Just because you do some painting on a component doesn't give the component a size. You are still responsible for setting the size. That is why you should always use a layout manager. It looks after all this size stuff for you so you don't have to worry.
I don't know why newbies always think they can't use a layout manager. Yes it takes a couple of more minutes to learn, but it saves you a lot of grief in the long run.
Background Panel shows a couple of approaches. Again they both assume you use a layout manager, so you may need to set the size manually.
I am new to the java (and programming in general) and I am trying to make my very first program. I'm stuck on the same problem for about 5 hours now, so I've decided to ask for help.
Basically I'm trying to make a program (2d game) that has about 20 positions on the board. Each position is either blue (owned by player1), red(owned by player2) or black(not owned by anyone).
The way I'm going about this is in main I've put a method that calls setup game, and then a method that plays game. I am working on the setup game, basically all it does is it makes an object of class Background (extends JPanel, and overrides paintComponent()) and 20 objects of class Position(extends JPanel, and overrides paintComponent()).
So far I'm stuck on putting those Position objects on top of Background object.
When I do:
Background background= new Background();
frame.getContentPane().add(background);
Position position1= new Position;
frame.getContentPane().add(position1);
frame.setVisible(true);
it shows only a circle and no background as I was hoping, if I first add position and then background, I only have background and no circle.
Anyway I'm new to the java and I am still having trouble founding my way around, however I've tried to search for solutions, and I've found many different solutions to this problem (such as adding position to background first, and then adding background to frame, etc.) but I couldn't make any of them to work.
I am aware that the way I am adding them both to frame is (very likely) completely wrong, but I wrote it that way so you would (hopefully) be sure that what I've wrote actually does show you that my code for each of those classes draws something on the screen.
PS: I didn't copy my code here as most of variable and method names aren't in English so it's fairly hard to read, but if you still think its needed, I will add it. Also I'm sorry for my probably stupid question, but I'm kinda hitting a wall here and I've no idea what else to try.
Basically I'm trying to make a program (2d game) that has about 20
positions on the board. Each position is either blue (owned by
player1), red(owned by player2) or black(not owned by anyone).
Painting in Swing by default never returns PreferredSize, is required to override getPreferedSize()
JPanel has implemented FlowLayout in API, this LayoutManager accepting only PreferredSize came from JComponents added to this container
after a.m. changes to post an SSCCE, short, runnable, compilable
Background background= new Background();
frame.getContentPane().add(background);
Position position1= new Position;
frame.getContentPane().add(position1);
A JFrame uses a BorderLayout by default. Also by default when you add a component to a Container that uses a BorderLayout the comopnent is added to the CENTER. Only one comonent can be added to the CENTER so your Position comonent replaces the Background component.
You want to add the Position to the Background and then add the Background to the frame. Something like:
Background background= new Background();
Position position1= new Position;
background.add(position1);
frame.add(background);
Note: there is no need to uses getContentPane() when adding a component to the frame.
The root panel should be a JFrame with a Container class underneath. When you call someRoot.window.container = yourJPanel, that loads the JPanel as the main component view of the JFrame. Note, a JFrame can only hold one JPanel but other JPanels can hold other JPanels. Just as you add the initial JPanel to the JFRam, a JPanel's own container can be another JPanel. Hope this helps.
Like this:
JPanel temp = new JPAnel();
frame.getContentPane().add(temp);
temp.getContentPane().add(new JPanel());
After these additions, there is a command that is illuding me but you call on JFrame to get it to refresh in real time. I think it is something like:
frame.validate(); //thanks #SMT
or something,
Try using something like
jPanelExampleName.validate();
jPanelExampleName.repaint();
after adding your JPanels.
It sounds like you want to use one JFrame and attach JPanels to it. This is how I personally would do it.
Declare your JFrame and JPanels
JFrame frame1 = new JFrame( "App Name");
JPanel panel1 = new JPanel();
JPanel panel2 = new JPanel();
JPanel panel3 = new JPanel();
JPanel panel4 = new JPanel();
Set the Background (I'm using colors but you get the idea)
panel1.setBackground(Color.orange);
panel2.setBackground(Color.orange);
panel3.setBackground(Color.orange);
panel4.setBackground(Color.orange);
Set your layout for the JFrame (I'm using BoxLayout not sure which would be best for you) You can find the best one for you and some sample code here. Also just set the default close operation.
frame1.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame1.setLayout( new BoxLayout( frame1.getContentPane(), BoxLayout.Y_AXIS ) );
Then Just attach your JPanels
frame1.add( panel1);
frame1.add( panel2);
frame1.add( panel3);
frame1.add( panel4);
frame1.pack();
frame1.setVisible( true );
This will allow you to use the JPanels you created and then change the colors via other methods.
I'm trying to make the background color of my program white (instead of gray).
I have a frame class that contains the program (a new instance of that frame class is instantiated in the main method). I have the following is the constructor:
this.setBackground(Color.WHITE);
Just in case it was somehow being blocked out by other panels, I added the same line to the constructor of every panel I have in my program (and I mean every one).
Still, nothing happened.
What could be wrong?
If that code is called in a JFrame's constructor you are not changing the JFrame's contentPane's color which is what needs to be done. Make that call on the contentPane:
getContentPane().setBackground(Color.WHITE);
The other JPanels added to the GUI shouldn't have their colors set, but should have their opaque property set to false via myPanel.setOpaque(false); This will let any image or color behind them to be visible. The exception to this is the contentPane which should always be opaque.
If this doesn't help, you need to tell us more (you need to do this anyway as your question leaves out much necessary and important detail).
Continuing my quest of learning Java by doing a simple game, i stumbled upon a little issue. My gameboard extends JPanel as well as each piece of the board. Now, this presents some problems:
Cant set size of each piece, therefore, each piece JPanel ocupy the whole JFrame, concealing the rest of the pieces and the background (gameboard).
Cant set the position of the pieces.
I have the default flow manager. Tried setbounds and no luck.
Perhaps i should make the piece to extend other JComponent?
Added image:
That's the piece, now the greyed area is also the piece! Checked that by making a mousePressed listener and assigning some stuff to it. Below the grey area, is the gameboard (or at least, should be!), another JPanel.
alt text http://img42.imageshack.us/img42/2227/screenshotvdy.png
Some code:
package TheProject;
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class GameWindow extends JFrame {
public GameWindow() {
setSize(800, 600);
setLocationRelativeTo(null);
Map map = new Map(800, 600, 2);
add(map);
MilitaryUnit imperialRussia = new MilitaryUnit(30, Color.BLACK, Color.YELLOW, Color.WHITE);
imperialRussia.setPreferredSize(new Dimension(30, 30));
add(imperialRussia);
}
}
This happens when i apply the pack() method:
alt text http://img442.imageshack.us/img442/5813/screenshot2ml.png
Packs around the Unit, not the map which is bigger and fills the JFrame.
For a game that has random movement of pieces you would probably use a "null layout".
Read the section from the Swing tutorial on Absolute Positioning for more information.
I wrote a few games using JPanel. Basically the way I use JPanel is like I'm using a Canvas, viz I draw directly on it by overriding the paint() method. The reason why I use JPanel is because I can determine the size of my game world, then use the setPreferredSize() to set the size of the panel. I then add the panel to a JScrollPane. So this will take care of the panning, etc.
Say I'm writing a 2D game. This is how I use JPanel. I have a logical map (a 2D array) which holds my game map. Say each location is 32x32 pixel. So you start drawing the ground and what is on that ground in that location. eg in x=1, y=2 which is screen location x=32, y=64, you draw the ground first, then draw what is on the ground. So a rough outline of the render loop would be something like this
for (int y = 0; y < map.length; y++)
for (int x = 0; x < map[y].length; x++) {
drawGround(map[y][x])
for very element on on map[y][x] - render them
}
You set a MouseListener listener to the JPanel, so every mouse click you translate back to the map eg. mouse click x=54, y=72 would correspond to x=1, y=2. The calculation is a bit tricky if you have an isometric view.
The thing you have to be careful here is that everytime when you scroll the panel via the scroll panel, paint() will be called. So it is good to render your game board on a BufferedImage and then in the paint() method just draw the BufferedImage otherwise it'll be too slow.
Have you tried NetBeans' visual editor? You can use it to drag, drop, and resize to your convenience Swing objects in Design View, and can then switch to Code View to see the generated code. You can learn that way.
Have you tried setPreferredSize(Dimension d)?
Edit: You need to call pack() on your JFrame, after you've added your components:
JFrame frame = new JFrame();
frame.setPreferredSize(new Dimension(800,600));
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(200,200));
frame.add(panel);
frame.pack();
frame.setvisible(true);
Also, you add a Map to your JFrame, which has the same dimensions as your JFrame - fine. But then afterwards, you add another component, to the default flowlayout. This cannot fit into your frame, as the Map already occupies 100% of the space.