I'm trying to resize a window dynamically using a Timer object, but not succeeding... I set the preferred size of the panel in the constructor, which sets the size of the window nicely, though only once. The preferred size changes after the program is initialized, but the window size stays the same. Why? Because the constructor is initialized only once and therefore isn't affected by the size change? If so, how could I get around this to resize the window in real-time?
I know this won't solve the problem in the exercise given in the beginning comments, so please ignore that :-)
/*
* Exercise 18.15
*
* "(Enlarge and shrink an image) Write an applet that will display a sequence of
* image files in different sizes. Initially, the viewing area for this image has
* a width of 300 and a height of 300. Your program should continuously shrink the
* viewing area by 1 in width and 1 in height until it reaches a width of 50 and
* a height of 50. At that point, the viewing area should continuously enlarge by
* 1 in width and 1 in height until it reaches a width of 300 and a height of 300.
* The viewing area should shrink and enlarge (alternately) to create animation
* for the single image."
*
* Created: 2014.01.07
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Ex_18_15 extends JApplet {
// Main method
public static void main(String[] args) {
JFrame frame = new JFrame();
Ex_18_15 applet = new Ex_18_15();
applet.isStandalone = true;
frame.add(applet);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
// Data fields
private boolean isStandalone = false;
private Image image = new ImageIcon("greenguy.png").getImage();
private int xCoordinate = 360;
private int yCoordinate = 300;
private Timer timer = new Timer(20, new TimerListener());
private DrawPanel panel = new DrawPanel();
// Constructor
public Ex_18_15() {
panel.setPreferredSize(new Dimension(xCoordinate, yCoordinate));
add(panel);
timer.start();
}
class DrawPanel extends JPanel {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image, 0, 0, this);
}
}
class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if(yCoordinate <= 50) {
yCoordinate++;
xCoordinate++;
}
else if(yCoordinate >= 300) {
yCoordinate--;
xCoordinate--;
}
panel.setPreferredSize(new Dimension(xCoordinate, yCoordinate));
repaint();
}
}
}
You need to re-pack your JFrame to resize it. For instance at the end of your ActionListener:
Window win = SwingUtilities.getWindowAncestor(panel);
win.pack();
A question for you though: Why in heaven's name is your class extending JApplet and not JPanel? Or if it needs to be an applet, why are you stuffing it into a JFrame?
Edit
Regarding your comment:
Wouldn't it usually be extending JFrame not JPanel? I'm stuffing it into a JFrame to allow it to run as an application as well as an applet. That's how 'Introduction to Java Programming' tells me how to do it :p Adding your code at the end of the actionPerformed method didn't do anything for me ;o
Most of your GUI code should be geared towards creating JPanels, not JFrames or JApplets. You can then place your JPanels where needed and desired without difficulty. Your book has serious issues and should not be trusted if it is telling you this.
Edit 2
Works for me:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
#SuppressWarnings("serial")
public class ShrinkingGui extends JPanel {
private static final int INIT_W = 400;
private static final int INIT_H = INIT_W;
private static final int TIMER_DELAY = 20;
private int prefW = INIT_W;
private int prefH = INIT_H;
public ShrinkingGui() {
new Timer(TIMER_DELAY, new TimerListener()).start();;
}
public Dimension getPreferredSize() {
return new Dimension(prefW, prefH);
}
private class TimerListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
if (prefW > 0 && prefH > 0) {
prefW--;
prefH--;
Window win = SwingUtilities.getWindowAncestor(ShrinkingGui.this);
win.pack();
} else {
((Timer)e.getSource()).stop();
}
}
}
private static void createAndShowGUI() {
ShrinkingGui paintEg = new ShrinkingGui();
JFrame frame = new JFrame("Shrinking Gui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(paintEg);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}
Related
This question is about Frames, Java and Processing.
This questions sounds pretty convoluted but its really not. I'll try keep this to a simple minimum. I'm creating a small ball in a maze game to get my head around physics and rendering. It's been a good experience so far but I've hit a bit of a brick wall.
The general layout I decided on was to contain PApplets within a AWT Frame and have the Frame close. The reason for this is because I was told that you should only have on instance of a Papplet at a time.
PApplet is the Applet class in Processing, a rendering library.
I have 3 classes here including the main
public class Menu extends PApplet
{
//images and buttons
PImage background, playbtn1, playbtn2, hsbtn1, hsbtn2, abbtn1, abbtn2, exbtn1, exbtn2;
FBox pBtn, hBtn, eBtn;
FWorld menu;
//simple constructor
public Menu()
{
}
public void setup()
{
size(600, 400);
smooth();
Fisica.init(this);
menu = new FWorld();
//loading and placing images
background = loadImage("MenuAlt.jpg");
System.out.println(background);
playbtn1 = loadImage("play1.gif");
playbtn2 = loadImage("play2.gif");
hsbtn1 = loadImage("high1.gif");
hsbtn2 = loadImage("high2.gif");
exbtn1 = loadImage("exit1.gif");
exbtn2 = loadImage("exit2.gif");
//loading and placing buttons
pBtn = new FBox(120, 150);
pBtn.setPosition(135, 215);
pBtn.setDrawable(false);
hBtn = new FBox(120, 150);
hBtn.setPosition(295, 215);
hBtn.setDrawable(false);
eBtn = new FBox(120, 150);
eBtn.setPosition(455, 215);
eBtn.setDrawable(false);
//add item to world
menu.add(pBtn);
menu.add(hBtn);
menu.add(eBtn);
}
public void draw()
{
image(background, 0, 0);
image(playbtn1, 80, 140);
image(hsbtn1, 237, 135);
image(exbtn1, 400, 140);
mouseOver();
menu.draw();
}
//close this frame an open a new level, high score or exit
//depending on what the use clicks
public void mousePressed()
{
FBody pressed = menu.getBody(mouseX, mouseY);
if (pressed == pBtn)
{
System.out.println("play game");
this.getParent().getParent().getParent().getParent().setVisible(false);
ExampleFrame x = new ExampleFrame(new Level("level1.txt"));
x.setLocation(this.getParent().getParent().getParent().getParent().getLocation());
}
if (pressed == hBtn)
{
System.out.println("high scores");
this.getParent().getParent().getParent().getParent().setVisible(false);
/* these are just for finding the parent
System.out.println(this.getName());
System.out.println(this.getParent().getName());
System.out.println(this.getParent().getParent().getName());
System.out.println(this.getParent().getParent().getParent().getName());
System.out.println(this.getParent().getParent().getParent().getParent().getName());
*/
ExampleFrame x = new ExampleFrame(new HighScores()); //for testing, you can change this to new menu()
x.setLocation(this.getParent().getParent().getParent().getParent().getLocation());
}
if (pressed == eBtn)
{
System.out.println("exit");
System.exit(0);
}
}
the exampleFrame class
public class ExampleFrame extends JFrame
{
PApplet app;
public ExampleFrame(PApplet emApp)
{
super("Ball Maze Game");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocation(200, 200);
app = emApp;
setSize(615,438);
setVisible(true);
setLayout(new BorderLayout());
add(app, BorderLayout.CENTER);
app.init();
}
}
the main
public class Main
{
public static void main(String[] args)
{
ExampleFrame x = new ExampleFrame(new Menu());
}
}
What needs to happen when mousePressed == ebtn is all the stuff in the Frame will be removed and a Highscores Screen will be loaded. highscores is almost the same as menu. There is no need to post code as there is enough here.
The second class is the one which acts as a frame and holds the PApplet
Bottom line, has anyone have any idea how to call the Frame methods from the PApplet or another way to remove all PApplets contents and load another PApplet in?
What needs to happen when mousePressed == ebtn is all the stuff in the Frame will be removed and a Highscores Screen will be loaded
The demo. below of a nested CardLayout adds an ActionListener instead of a MouseListener. It reacts to both mouse and keyboard input.
There are a multitude of other ways to include more than one GUI element in the same screen space. Off the top of my head, JTabbedPane, JSplitPane, JDesktopPane/JInternalFrame, popping the high scores in a JDialog or JOptionPane..
Screenshots
CardLayoutDemo.java
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class CardLayoutDemo {
public static void main(String[] args) {
Runnable r = new Runnable () {
public void run() {
final JRadioButton game = new JRadioButton("Game", true);
JRadioButton highScores = new JRadioButton("High Scores");
ButtonGroup bg = new ButtonGroup();
bg.add( game );
bg.add( highScores );
JPanel buttons = new JPanel(new
FlowLayout(FlowLayout.CENTER, 5, 5));
buttons.add( game );
buttons.add( highScores );
JPanel gui = new JPanel(new BorderLayout(5,5));
gui.add(buttons, BorderLayout.SOUTH);
final CardLayout cl = new CardLayout();
final JPanel cards = new JPanel(cl);
gui.add(cards);
cards.add(new JLabel("Level 1"), "game");
cards.add(new JLabel("High Scores"), "scores");
ActionListener al = new ActionListener(){
public void actionPerformed(ActionEvent ae) {
if (game.isSelected()) {
cl.show(cards, "game");
} else {
cl.show(cards, "scores");
}
}
};
game.addActionListener(al);
highScores.addActionListener(al);
JOptionPane.showMessageDialog(null, gui);
}
};
SwingUtilities.invokeLater(r);
}
}
In order to answer How to call the Frame methods from the PApplet?, I have modified your code snippet to bare minimum. In this modified version when the user click mouse button a System.out is fired.
Now there are two ways in which you can access your Frame object. But before that let me state these two points:
When you create a PApplet like new ExampleFrame(new Menu()); and add it in your JFrame like this add(app, BorderLayout.CENTER); then a complex hierarchy of windows/panels are created.
Like this:
javax.swing.JPanel
javax.swing.JLayeredPane
javax.swing.JRootPane
test.ExampleFrame
PApplet provides a public field for setting and accessing your frame object. And amazingly it is called frame :). You can set it before calling app.init();
>>Code
** Checkout the comments in the code**
Modified ExampleFrame.java
import java.awt.BorderLayout;
import javax.swing.JFrame;
import processing.core.PApplet;
public class ExampleFrame extends JFrame
{
private static final long serialVersionUID = 4792534036194728580L;
PApplet app;
public ExampleFrame(PApplet emApp)
{
super("Ball Maze Game");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setLocation(200, 200);
app = emApp;
setSize(615,438);
setVisible(true);
setLayout(new BorderLayout());
add(app, BorderLayout.CENTER);
// Setting my frame object
app.frame = this;
app.init();
}
// Sample Method
public void sampleMethod(String msg)
{
System.out.println("I think '"+ msg +"' called me !!");
}
}
Modified Menu.java
import java.awt.Container;
import processing.core.PApplet;
import processing.core.PImage;
public class Menu extends PApplet
{
private static final long serialVersionUID = -6557167654705489372L;
PImage background;
static String tab = "";
//simple constructor
public Menu()
{
}
public void setup()
{
size(600, 400);
smooth();
background = loadImage("C:/temp/background.jpg");
}
public void draw()
{
image(background, 0, 0);
}
public void mousePressed()
{
Container p = getParent();
tab = "";
// FIRST WAY OF ACCESSING PARENT FRAME
while(p != null)
{
//printParentTree(p);
if(p instanceof ExampleFrame)
{
ExampleFrame myframe = (ExampleFrame)p;
myframe.sampleMethod("First Way");
break;
}
p = p.getParent();
}
// SECOND WAY OF ACCESSING PARENT FRAME
if(frame != null && (frame instanceof ExampleFrame))
{
ExampleFrame myframe = (ExampleFrame)p;
myframe.sampleMethod("Second Way");
}
}
void printParentTree(Container p)
{
System.out.println(tab+p.getClass().getName());
tab +='\t';
}
}
Checkout the public void mousePressed() method.
For completeness, I am also including Main.java.
public class Main {
public static void main(String[] args){
new ExampleFrame(new Menu());
}
}
Now to answer Remove all PApplets contents and load another PApplet in
Well I have not tested it. But you can add a JPanel to your JApplet and do all your drawing on that i.e creating child controls etc. When feel like redrawing then call JPanel.removeAll(). Which as per javadoc:
Removes all the components from this
container. This method also notifies
the layout manager to remove the
components from this container's
layout via the removeLayoutComponent
method.
After this call repaint on the JPanel. Try it out, it might work :).
Right now I'm working on some practice problems for a Computer science test and I've run into one that is giving me nothing but trouble. I understand swing for the most part but I don't understand how to create and move a shape across a Panel. This is what I have so far:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class SwingStarting extends JFrame {
public JPanel innerPanel; // panel containing moving shape
public JButton pauseResumeButton;
public static final int LEFT = 0;
public static final int RIGHT = 1;
public int direction = LEFT;
// The dimensions of the inner panel. To simplify this problem,
// assume the panel will always have these dimensions.
public static final int PANEL_WIDTH = 600;
public static final int PANEL_HEIGHT = 400;
public Timer movementTimer = new Timer(10,new TimerListener());
public SwingStarting() {
innerPanel = new ShapePanel();
innerPanel.setPreferredSize(
new Dimension(PANEL_WIDTH,PANEL_HEIGHT));
innerPanel.setBorder(
BorderFactory.createLineBorder(Color.BLACK, 2));
pauseResumeButton = new JButton("pause");
add(innerPanel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel(new FlowLayout());
buttonPanel.add(pauseResumeButton);
add(buttonPanel, BorderLayout.SOUTH);
setDefaultCloseOperation(EXIT_ON_CLOSE);
pack();
setVisible(true);
movementTimer.start();
} // end constructor
public class ShapePanel extends JPanel {
public void paint(Graphics gc) {
super.paintComponent(gc);
int circleX = 0;
int circleY = 100;
gc.setColor(Color.RED);
gc.fillOval(circleX,circleY,20,20);
}
} // end inner class
public class TimerListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
} // end actionPerformed
} // end inner class
public static void main(String args[]) {
new SwingStarting();
} // end main
}// end class
So far I've created a small red circle. But how do I make it cross the screen horizontally? Any help is greatly appreciated.
In your panel class why not make a timer with an Action listener?
// Make the shape here or earlier whenever you want.
// By the way, I would change ShapePanel's paint method to paintComponent because it extends JPanel not JFrame
// Create the object by giving ShapePanel a constructor
ShapePanel s = new ShapePanel();
ActionListener listener = new ActionListener()
{
public void actionPerformed(ActionEvent event)
{
// IN HERE YOU MOVE THE SHAPE
s.moveRight();
// Use any methods for movement as well.
repaint();
}
};
Timer timer = new Timer(5, listener);
timer.start();
Also, because you are using swing you want to make sure you do all your motions and things on one EDT.
Try using this in your main method instead of making a new SwingStarting
public static void main(String[] args)
{
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run()
{
createAndShowGUI();
}
});
}
I am dragging a JLabel around the screen, and when I release above the JPanel it is supposed to snap to where it completely covers the JPanel. Also, if I release anywhere else it is supposed to snap to its original position. I have the snap part, but I don't know how to tell if it is over the JPanel. I have my code below.
import java.awt.Color;
java.awt.Dimension;
import javax.swing.*;
import javax.swing.event.MouseInputAdapter;
import java.awt.event.MouseEvent;
public class Main {
public static final int CARD_HEIGHT = 97;
public static final int CARD_WIDTH = 73;
/**
* Mouse Handler components
* Changes the location of the JLabel with the mouse
*/
public static MouseInputAdapter mouseHandler = new MouseInputAdapter(){
public int labelDisX;
public int labelDisY;
public void mousePressed(MouseEvent e) {
labelDisX = e.getX();
labelDisY = e.getY();
//move the card above all others
e.getComponent().getParent().setComponentZOrder(e.getComponent(), 0);
e.getComponent().getParent().repaint();
}
public void mouseReleased(MouseEvent e) {
//if not above panel, then move to original spot
if(!abovePanel()) {
e.getComponent().setLocation(labelDisX, labelDisY);
}
}
public void mouseDragged (MouseEvent e) {
JPanel panel = (JPanel) e.getComponent().getParent();
//get preliminary new X coordinate
int newX = e.getComponent().getX() + e.getX() - labelDisX;
//get preliminary new Y coordinate
int newY = e.getComponent().getY() + e.getY() - labelDisY;
//Not moved off edges of JFrame
if(newX > panel.getWidth() - CARD_WIDTH) {
newX = panel.getWidth() - CARD_WIDTH;
}
if(newY > panel.getHeight() - CARD_HEIGHT) {
newY = panel.getHeight() - CARD_HEIGHT;
}
if(newX < 0) { newX = 0; }
if(newY < 0) { newY = 0; }
e.getComponent().setLocation(newX, newY);
}
};
/**
* check to see if the JLabel is above the JPanel
* #return
*/
public static boolean abovePanel() {
return false;
}
/**
* Adds ability to drag to JLabel
* #param label
*/
public static void addDrag( JLabel label) {
System.out.println("Adding drag");
label.addMouseMotionListener(mouseHandler);
label.addMouseListener(mouseHandler);
}
public static void main(String[] args) {
// Create a JFrame
JFrame frame = new JFrame("Example Frame");
// JPanel to add JLabels to
JPanel panel = new JPanel();
// Add a drop target text area in the center of the frame
DropTargetArea dropPanel = new DropTargetArea();
dropPanel.setPreferredSize(new Dimension(CARD_WIDTH, CARD_HEIGHT));
dropPanel.setBackground(Color.gray);
panel.add(dropPanel);
// Add several draggable labels to the container
JLabel blue = new JLabel();
blue.setOpaque(true);
blue.setPreferredSize(new Dimension(CARD_WIDTH, CARD_HEIGHT));
blue.setBackground(Color.blue);
addDrag(blue);
panel.add(blue);
// Add the container to the frame
frame.add(panel);
// Display the frame
frame.setPreferredSize(new Dimension(400,400));
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setVisible(true);
frame.pack();
}
}
I've done this using a JLayeredPane that holds a JPanel that itself holds a grid of JPanels using BorderLayout, with each smaller JPanel representing a chess square, and each smaller JPanel can accept a single JLabel. I added the MouseAdapter to the JLayeredPane itself, and when clicked, it checks to see if a moveable JLabel is located below the click. If so, the JLabel is raised up to the JLayeredPane's DRAG_LAYER, and then when released, check which JPanel the mouse cursor is over, and drop the JLabel if it is a valid square, otherwise return it to its original position. You can see my code here.
Every time I run this piece of code, the output is a dialog box that appears at the top left hand corner of the screen and the title does not show.
Is there any way that I can change this so that the dialog appears at the middle and of acceptable size?
Code:
public class Test {
public static void main(String[] args) {
JFrame f = new JFrame();
final JDialog dialog = new JDialog(f, "Hello world", true);
Timer timer = new Timer(10000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
dialog.dispose();
}
});
timer.setRepeats(false);
timer.start();
dialog.setVisible(true);
System.out.println("Dialog closed");
}
}
Absolutely. By default, a JDialog (or a JFrame) will appear like that. You need to set bounds on it:
dialog.setBounds(xPosition, yPosition, width, height);
However, if you just set some magic numbers for it, this will not scale well to other systems. Instead, get the screen dimension, and set off of that:
//static and final because no reason not to be. Insert this at the class definition
static final Dimension SCREEN_DIMENSION = Toolkit.getDefaultToolkit().getScreenSize();
...
//I'd also make this static and final and insert them at the class definition
int dialogWidth = SCREEN_DIMENSION.width / 4; //example; a quarter of the screen size
int dialogHeight = SCREEN_DIMENSION.height / 4; //example
...
int dialogX = SCREEN_DIMENSION.width / 2 - dialogWidth / 2; //position right in the middle of the screen
int dialogY = SCREEN_DIMESNION.height / 2 - dialogHeight / 2;
dialog.setBounds(dialogX, dialogY, dialogWidth, dialogHeight);
Alternatively, if you add components to the JDialog, then call
dialog.pack();
the dialog will now be the minimum size to accommodate the components. If you are using components that should be packed tight, use this method; then you don't have to painstakingly construct the right width and height by hand.
"Is there any way that I can change this so that the dialog appears at the middle and of acceptable size?"
If you just add components to it, pack it, and set it location relative to null, it should work fine
It is preferred to .pack() instead of setting a size. For pack to work, you need to actually add components. the .pack() will do exactly as it's name suggest - pack the frame with respecting all the added components' preferred sizes.
Also with setLocationRelativeTo() you set the dialog loation relative to a component. If you use null, it will be centered on the screen always. But if you set the location relative to its parent, the frame, it will appear centered over the frame.
I have absolutely no idea what you're trying to achieve with the timer, so I just prefer to no-comment
See example
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.Timer;
public class Test {
public static void main(String[] args) {
JFrame f = new JFrame();
final MyDialog dialog = new MyDialog(f, "Title", true);
Timer timer = new Timer(10000, new ActionListener() {
public void actionPerformed(ActionEvent e) {
dialog.setVisible(false);
dialog.dispose();
}
});
timer.setRepeats(false);
timer.start();
dialog.setVisible(true);
System.out.println("Dialog closed");
}
private static class MyDialog extends JDialog {
public MyDialog(JFrame frame, String title, boolean modal) {
super(frame, title, modal);
setLayout(new BorderLayout());
add(new JButton("NORTH"), BorderLayout.NORTH);
add(new JButton("SOUTH"), BorderLayout.SOUTH);
add(new JButton("EAST"), BorderLayout.EAST);
add(new JButton("WEST"), BorderLayout.WEST);
add(new JButton("CENTER"), BorderLayout.CENTER);
pack();
setLocationRelativeTo(null);
}
}
}
As a side note, you should be running Swing apps from the Event Dispatch Thread (EDT) like this
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable(){
public void run() {
// the code from your main method here
}
});
}
Add these lines of code between timer.start(); and dialog.setVisible(true); statements -
timer.start();
dialog.setPreferredSize(new Dimension(50, 150));//set your desired size
dialog.pack();
Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension screenSize = toolkit.getScreenSize();
int iWidth = (screenSize.width - dialog.getWidth()) / 2;
int iHeight = (screenSize.height - dialog.getHeight()) / 2;
dialog.setLocation(iWidth, iHeight);
dialog.setVisible(true);
This code will set the dialog to center of your screen.
Add this line
dialog.setBounds(0, 0, 1000, 500);
The title of this quesiton speaks for itself. I am making a clone of minesweeper using a JFrame and have just finished the starting screen where the player selects a game size. When a button is clicked, the Frame is supposed to clear ready for the game screen. When I click a button, the button remains in the "pressed" state and the JFrame freezes and I have to close it down. What am I doing wrong?
Code:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Minesweeper extends JFrame implements ActionListener{
JLabel starttitle;
ButtonObject[] gamefield;
JFrame frame;
JPanel startscreen;
JPanel gamescreen;
int gamesize;
JButton ten;
JButton tfive;
JButton fifty;
GridLayout layout;
public Minesweeper()
{
frame = new JFrame("Minesweeper");
frame.setSize(500,500);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);;
startscreen = new JPanel();
startScreen();
}
public void startScreen()
{
ten = new JButton("10 x 10");
tfive = new JButton("25 x 25");
fifty = new JButton("50 x 50");
starttitle = new JLabel("Welcome to minesweeper. Click a game size to begin.");
frame.add(startscreen);
startscreen.add(starttitle);
startscreen.add(ten);
startscreen.add(tfive);
startscreen.add(fifty);
ten.addActionListener(this);
tfive.addActionListener(this);
fifty.addActionListener(this);
}
public void gameScreen()
{
frame.getContentPane().removeAll();//freezes JFrame
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource()==ten)
{
gamesize = 10;
gameScreen();
}
else if(e.getSource()==tfive)
{
gamesize = 25;
gameScreen();
}
else if(e.getSource()==fifty)
{
gamesize = 50;
gameScreen();
}
else
{
System.out.println("Fatal error");
}
}
public static void main(String[] args)
{
new Minesweeper();
}
}
It doesn't freeze, call repaint() method of your frame, and all components will be clear.
just add next line in your actionPerformed():
frame.repaint();
just like this..
public void gameScreen()
{
frame.getContentPane().removeAll();
frame.repaint();
}
JFrame's default LayoutManager is Borderlayout
all changes to the already visible Swing GUI (add, remove, resize, modify) must propertly to notify used LayoutManager
standard notifier for JFrame is frame.(re*)validate and frame.repaint()**,
*- in Java7 and newer versions
** - not required in all cases(for JTextComponents, JFrame.pack(), e.i.), by default is better to use this code line too