Archived

This topic is now archived and is closed to further replies.

RobAU78

Java GUI Help

Recommended Posts

Hey everyone, This seems to be the best forum for my question I''m currently working on a simple space strategy game written in Java and I think I might need help with its GUI. I would like to implement a GUI such that there is a column of buttons on the right-hand side of the screen, where each button accesses a different window (e.g. a galaxy window, planet window, ship window, etc.). The appropriate window is then displayed in the remainder of the screen. In terms of actual Java code, what I have right now is a standard JFrame and a JPanel that contains everything else (all the windows and buttons). The buttons are standard JButtons. Each type of window has its own class, and all of the classes extend JPanel (so they are, in effect, containers themselves). I think that the proper layout I should have for the GUI is the grid layout, but I''m not sure. Also, does using the setVisible method make a panel appear on top, even when the other panels are also visible, or do I need to make them invisible again? Finally, how do I make my program start in fullscreen mode? Thanks, Rob

Share this post


Link to post
Share on other sites
For your layout you might want to look into using a JTabbedPane, with the tabs replacing your buttons. Either that or stick with your manual implementation if you want, in which case a BorderLayout (with main game screens positioned center) and the buttons in a BoxLayout on the east or west edges. This way your center resizes to fill all the avalible space.

For fullscreen, look into GraphicsDevice and methods like setFullScreenWindow(), isDisplayChangeSupported() and setDisplayMode().

Share this post


Link to post
Share on other sites
Hey OrangyTang,

Thanks for your reply. I took your advice, and I have been able to get the menu buttons on the right side of the screen while the rest of the space is taken up by the windows. However, there is a problem. Only the last window added to the main panel ever appears! It seems that I need to do something else to get the windows to load on top of one another. How can I do this?

Also, for the GraphicsDevice methods, how would I go about fitting in an instance of the GraphicsDevice class in my program?

Thanks,
Rob

Share this post


Link to post
Share on other sites
Border layout only allows one component in the middle, so if you add more than one then the second one will replace the first. You'll need to add something like another JPanel first with a layout manager containing everything you want in the middle. Perhaps another border layout or box layout depending on how your middle should be arranged.

Some example fullscreen code. Only gives you a fullscreen canvas though, if you're adding Awt or swing widgets as well you'll probably have to do things slightly differently.

import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

import java.awt.GraphicsEnvironment;
import java.awt.image.BufferStrategy;

/**
* A class that sets up the screen and drawing surface according to the values
* passed to it.
* Defaults to 800x600 and 16bit colour if invalid arguments are specified. Refresh rate is not specified
* (REFRESH_RATE_UNKNOWN) so it will default to the users settings (typically as high as possible).
*
* Fullscreen mode is attempted - if not hardware accelerated the user will be prompted
* as to whether to use it or not. If fullscreen is not supported a JFrame will be created
* with a canvas of the specified size.
*
* Regardless of whether the screen created is fullscreen or not, a double buffered
* buffer strategy will be created and can be retrived via the get method.
*
* To shut down properly (especially if in fullscreen mode) the close() method should be called.
* This will exit fullscreen mode properly and restore previous display settings. In windowed
* mode it simply hides the frame and attached canvas.
*
* @author John Campbell
*
*/


public class ScreenManager
{
// Global variables

private boolean active;
private boolean useFullscreen;

private int xResolution;
private int yResolution;
private int colourDepth;

private Window fullscreenWindow;
private Canvas mainCanvas;


private GraphicsDevice graphicsDev;
private GraphicsConfiguration graphicsConfig;

private DisplayMode oldDisplayMode;
private DisplayMode currentDisplayMode;

// Buffer stratergy is attacted to either the window or canvas

private BufferStrategy bufferStrategy;


private JFrame mainFrame;
private PrintWriter log;



// Display mode constants

public static final int RESOLUTION_320_BY_200 = 0;
public static final int RESOLUTION_320_BY_240 = 1;
public static final int RESOLUTION_400_BY_300 = 2;
public static final int RESOLUTION_480_BY_360 = 3;
public static final int RESOLUTION_512_BY_384 = 4;
public static final int RESOLUTION_640_BY_400 = 5;
public static final int RESOLUTION_640_BY_480 = 6;
public static final int RESOLUTION_800_BY_600 = 7;
public static final int RESOLUTION_960_BY_720 = 8;
public static final int RESOLUTION_1024_BY_768 = 9;


/** Basic constructor.
* Accepts a resolution mode (RESOLUTION_800_BY_600, etc.) and a colour depth (8, 16 or 32)
* as well as a title string to display on the JFrame created.
*
* Attempts full screen mode, but will create a frame and canvas if full screen mode
* is not supported. A buffer strategy will be created with a front and back buffer
* (double buffered).
*
*/

public ScreenManager(String frameTitle, int resolution, int colourD, boolean windowedMode)
{
// log = GlobalOptions.getInstance().getLog();

// log.println("Creating screen manager...");


// Set resolution

xResolution = 800;
yResolution = 600;

if (resolution == RESOLUTION_320_BY_200)
{
xResolution = 320;
yResolution = 200;
}
else if (resolution == RESOLUTION_320_BY_240)
{
xResolution = 320;
yResolution = 240;
}
else if (resolution == RESOLUTION_400_BY_300)
{
xResolution = 400;
yResolution = 300;
}
else if (resolution == RESOLUTION_480_BY_360)
{
xResolution = 480;
yResolution = 360;
}
else if (resolution == RESOLUTION_512_BY_384)
{
xResolution = 512;
yResolution = 384;
}
else if (resolution == RESOLUTION_640_BY_400)
{
xResolution = 640;
yResolution = 400;
}
else if (resolution == RESOLUTION_640_BY_480)
{
xResolution = 640;
yResolution = 480;
}
else if (resolution == RESOLUTION_800_BY_600)
{
xResolution = 800;
yResolution = 600;
}
else if (resolution == RESOLUTION_960_BY_720)
{
xResolution = 960;
yResolution = 720;
}
else if (resolution == RESOLUTION_1024_BY_768)
{
xResolution = 1024;
yResolution = 768;
}

// Check colour depth

if (colourD != 8 || colourD != 16 || colourD != 32)
{
// If not a valid colour depth, default to 16

colourD = 16;
}

colourDepth = colourD;


GraphicsEnvironment graphicsEnv = GraphicsEnvironment.getLocalGraphicsEnvironment();
graphicsDev = graphicsEnv.getDefaultScreenDevice();

// Need to restore old mode on exit, so save now.

oldDisplayMode = graphicsDev.getDisplayMode();

if (graphicsDev.isFullScreenSupported() == true)
{
// Fullscreen mode ok

System.out.println("Hardware fullscreen mode supported...");

useFullscreen = true;
}
else
{
// Fullscreen not supported

int confirm = JOptionPane.showConfirmDialog(null,
"Fullscreen mode not hardware accelerated, Use anyway?",
"Fullscreen not supported",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE);

if (confirm == JOptionPane.YES_OPTION)
useFullscreen = true;
else
useFullscreen = false;
}

if (windowedMode)
useFullscreen = false;


// Create frame to attach window or canvas.

mainFrame = new JFrame(frameTitle);
mainFrame.setVisible(true);
// mainFrame.setResizable(false);



active = true;


// NB, if createFullscreenWindow fails then it will drop out and change useFullscreen to false.

if (useFullscreen)
{
createFullscreenWindow();
}

if (useFullscreen == false)
{
createWindowedCanvas();
}

}



/** Tries to create a fullscreen window as specified. If fullscreen display mode is
* not supported it will abort and a windowed canvas will be created instead.
*/

private void createFullscreenWindow()
{
fullscreenWindow = new Window(mainFrame);

graphicsDev.setFullScreenWindow(fullscreenWindow);

// Check if possible to switch display modes

if (graphicsDev.isDisplayChangeSupported() )
{
// Changes supported, all good :)

}
else
{
// Cannot change, must run in window.

JOptionPane.showMessageDialog(null,
"Display mode cannot be changed, running in a window.",
"Cannot change display mode",
JOptionPane.ERROR_MESSAGE);

fullscreenWindow = null;
graphicsDev.setFullScreenWindow(null);
useFullscreen = false;
return;
}

currentDisplayMode = new DisplayMode(xResolution, yResolution, colourDepth, DisplayMode.REFRESH_RATE_UNKNOWN);
graphicsDev.setDisplayMode(currentDisplayMode);

fullscreenWindow.createBufferStrategy(2);
bufferStrategy = fullscreenWindow.getBufferStrategy();

graphicsConfig = fullscreenWindow.getGraphicsConfiguration();


mainFrame.setIgnoreRepaint(true);
fullscreenWindow.setIgnoreRepaint(true);
}



/** Creates a canvas on the JFrame of the specified dimensions.
* A fall back if fullscreen mode is not supported.
*/

private void createWindowedCanvas()
{
Container c = mainFrame.getContentPane();

graphicsConfig = c.getGraphicsConfiguration();

// Create canvas with buffer strategy

mainCanvas = new Canvas(graphicsConfig);
mainCanvas.setSize(xResolution, yResolution);

mainCanvas.setVisible(true);
mainCanvas.setIgnoreRepaint(true);

c.add(mainCanvas, BorderLayout.CENTER);

mainCanvas.createBufferStrategy(2);
bufferStrategy = mainCanvas.getBufferStrategy();

// mainFrame.pack();



// Create listener for handling resized events

ResizedListener resizedListener = new ResizedListener();
mainCanvas.addComponentListener(resizedListener);


}


public void addKeyListener(KeyListener KHandler)
{
System.out.println("Attaching key listener: " + KHandler + " to " + this);


if (useFullscreen)
{
// Add to window

fullscreenWindow.addKeyListener(KHandler);
}
else
{
// Add to canvas

mainCanvas.addKeyListener(KHandler);
}

mainFrame.addKeyListener(KHandler);
}


public void addMouseListener(MouseListener MHandler)
{
if (useFullscreen)
{
// Add to window

fullscreenWindow.addMouseListener(MHandler);
}
else
{
// Add to canvas

mainCanvas.addMouseListener(MHandler);
}
}

public void addMouseMotionListener(MouseMotionListener MHandler)
{
System.out.println("Attaching mouse motion listener: " + MHandler + " to " + this);

if (useFullscreen)
{
// Add to window

fullscreenWindow.addMouseMotionListener(MHandler);
}
else
{
// Add to canvas

mainCanvas.addMouseMotionListener(MHandler);
}
}


/** Closes frames, windows and canvas', and returns the display to its original settings
* if they have been changed in full screen mode.
*/

public void close()
{
if (active)
{
if (useFullscreen)
{
System.out.println("Exiting fullscreen mode...");

// Switch back to previous display mode and leave fullscreen mode.

try
{
graphicsDev.setDisplayMode(currentDisplayMode);
}
catch (UnsupportedOperationException e)
{
System.out.println("Error: close() method has already been called");
}

graphicsDev.setFullScreenWindow(null);

mainFrame.setVisible(false);
mainFrame.dispose();
active = false;
}
else
{
System.out.println("Closing screen manager...");

// Close frame

mainFrame.setVisible(false);
mainFrame.dispose();
mainFrame = null;
active = false;
}
}
}



public void resize()
{
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();

screenSize.height = (int)(screenSize.height*0.8);
screenSize.width = (int)(screenSize.width*0.8);

mainFrame.setSize(screenSize);
}




/** Returns true if in full screen mode.
*/

public boolean isFullScreen()
{
return useFullscreen;
}


/** Returns the graphics configuration being used.
*/

public GraphicsConfiguration getGraphicsConfiguration()
{
return graphicsConfig;
}


/** Returns the current buffer strategy for the screen object.
*/

public BufferStrategy getBufferStrategy()
{
return bufferStrategy;
}


/** Gets the JFrame that the window or canvas is attached to.
* Allows attaching window listeners and key handlers etc.
*/

public JFrame getMainFrame()
{
return mainFrame;
}


public int getXResolution()
{
return xResolution;
}

public int getYResolution()
{
return yResolution;
}





// Inner class for handling resized events

class ResizedListener implements ComponentListener
{
public void componentResized(ComponentEvent e)
{
xResolution = mainCanvas.getWidth();
yResolution = mainCanvas.getHeight();
}


public void componentMoved(ComponentEvent e) {}

public void componentShown(ComponentEvent e) {}

public void componentHidden(ComponentEvent e) {}


}


}


[edited by - OrangyTang on October 15, 2003 11:01:55 AM]

Share this post


Link to post
Share on other sites
OK, I got it to work! I took your advice and made another JPanel called screenPanel (which contains the screens/windows) and added it to mainPanel using BorderLayout.CENTER. I also made a JPanel called buttonPanel for all the buttons. I think I''m actually going to use a null layout for the buttonPanel and arrange all the buttons manually. As for the interface, here is how I coded the switching of screens:

1. I declared global instances of each screen class and set them to null (e.g. PlanetScreen pscr = null.
2. The GalaxyScreen class instance is created and set to visible (it is the default screen).
3. When the user clicks on a button, it first sets the Galaxy Screen to not visible, and then sets all the other screen objects to null (in case they weren''t - although maybe using if statements would be more memory/time-efficient?). Then it calls the constructor for the appropriate screen object (e.g. pscr = new PlanetScreen().

What do you think? Is this a good way to do what I want the program to do?

Thanks,
Rob

Share this post


Link to post
Share on other sites