Swing gui not displaying, but no errors? - java

I am working on a java program that solves sudoku puzzles. So far all I have coded is a class that draws the board with swing, and another class that calls the gui class.
When I try and run the program nothing happens. No error messages are shown, but the gui doesn't show either. It immediately terminates.
Here is my code so far:
Gui class:
package sudoku;
import java.awt.*;
import javax.swing.*;
public class Gui {
Gui gui;
JPanel board;
JPanel subBoard[][];
GridLayout layout;
JLabel square[][];
public void load() {
gui = new Gui();
gui.setUp();
gui.buildBoard();
}
private void setUp() {
layout = new GridLayout(3, 3);
board = new JPanel(layout);
subBoard = new JPanel[3][3];
square = new JLabel[9][9];
}
private void buildBoard() {
// set up board
board.setSize(800, 600);
board.setVisible(true);
int mod = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
// add subBoards to board
subBoard[i][j] = new JPanel();
board.add(subBoard[i][j]);
subBoard[i][j].setLayout(layout);
subBoard[i][j].setVisible(true);
// add textfields to each subBoard
square[i + mod][j + mod] = new JLabel();
subBoard[i][j].add(square[i + mod][j + mod]);
square[i + mod][j + mod].setVisible(true);
}
mod += 3;
}
}
}
main class:
package sudoku;
public class SudokuSolver {
public static void main(String[] args) {
Gui gui = new Gui();
gui.load();
}
}
I tried running it in both eclipse and netbeans but got the same result both times. Why does this not work?

There is no displayable window such as a JFrame being used in the application.
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
JFrame frame = new JFrame("New GUI");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Gui gui = new Gui();
gui.load();
frame.add(gui.getBoard()); // add getBoard getter
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
Remove the class member variable gui within Gui. This is shadowing variables in the outer class Gui so use the latter instead. Also override getPreferredSize to give the board a size when frame.pack() is invoked.

Make GUI extend JFrame firstly. Then in your main method call gui.setVisible(true);.
public class Gui extends JFrame { }
Then in main.
Gui gui = new Gui();
gui.load();
gui.setVisible(true);

You can not show directly Jpanel. for show gui you must use JFrame or any other Window class(JDialog, JWindow...) and after that set visible property true.
setVisible(true);
public class Gui extends JFrame {
Gui(){
...
setVisible(true);
setSize(300,400);
}
...
}

Related

How to generate GUI with multiple buttons and incrementing labels on them?

I am trying to generate a GUI using swing that creates a frame with 100 buttons and every button has a "label" on it from on 1 to a 100.
What I have tried:
import javax.swing.*;
import java.awt.*;
public class ButtonScreen extends JFrame{
JFrame frame = new JFrame();
int rows=10;
int cols=10;
JButton[][] button = new JButton[rows][cols];
JTextArea screen = new JTextArea();
JPanel bpanel = new JPanel();
public static void main(String[] args) {
ButtonScreen bs = new ButtonScreen();
bs.setVisible(true);
}// end of main
public ButtonScreen(){
super("Welcome to the ButtonScreen Program!");
setDefaultCloseOperation(EXIT_ON_CLOSE);
bpanel.setLayout(new GridLayout(rows,cols));
for(int i=0;i<button.length;i++){
for(int j=0;j<button.length;j++){
button[i][j]=new JButton(""+i+j);
bpanel.add(button[i][j]);
}
}
add(bpanel);
}//end of constructor
}//end of class
This works just fine, but it creates buttons with "labels" (meaning string parameters at line 26) and also these labels, are not one string or one integer but it is a dillusion of the of i right next to j counter. So my second attempt, after some corrections, was:
import java.awt.*;
import javax.swing.*;
public class LabArr extends JFrame{
JFrame frame = new JFrame();
int rows=10;
int cols= 10;
int i=0;
JButton[][] button = new JButton[rows][cols];
JLabel[] label = new JLabel[100];
public static void main(String[] args) {
LabArr la = new LabArr();
la.setVisible(true);
}//end of main
public LabArr(){
super("title");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new GridLayout(rows,cols));
for(i=0;i<label.length;i++){
label[i]= new JLabel(toString(i));
}
for(int i=0;i<button.length;i++){
for(int j=0;j<button.length;j++){
button[i][j]= new JButton(""+label[j]);
add(button[i][j]);
}
}
}//end of constructor
public String toString(int k){
k=i;
String s;
s=""+k;
return s;
}
}//end of class
My goal using that was to create an array of JLabel objects and then match every JLabel element to one from the JButton array.
So, first of all I would like to know to which object the methods setLayout and setDefaultCloseOperation refer to.
Second, "Does the toString method need to refer to an object at the line I am using it?". And finally, what am I missing?
This will create a single frame with buttons from 1 to 100.
import javax.swing.*;
import java.awt.GridLayout;
public class HundredButtonGrid{
public static void main(String[] args){
JFrame frame = new JFrame("100 buttons");
frame.setLayout(new GridLayout(10, 10));
for(int i = 0; i<100; i++){
frame.add( new JButton( "" + (i + 1) ) );
}
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
I've addressed a few things.
I just use 1 index because the GridLayout takes care of the x/y values.
I used parenthesis to add the index to 1 so that it doesn't end up concatenating them by string.
I've set the default close operation to exit, you can have it do other things too. Like JFrame.DISPOSE_ON_CLOSE so the window will go away, but not terminate the application.
I didn't extend JFrame, I created a separate instance. In your case you have extended JFrame, so when you call setLayout it is being called on the instance you're creating. An alternative way to say it is this.setLayout same with setDefaultCloseOperation.
Hope this will help you with your problem, kindly see the code below:
public class LabArr extends JFrame{
JFrame frame = new JFrame();
int rows=10;
int cols= 10;
int counter = 0;
JButton[][] button = new JButton[rows][cols];
JLabel[] label = new JLabel[rows*cols];
public static void main(String[] args) {
DemoApplication la = new DemoApplication();
la.setVisible(true);
}//end of main
public LabArr(){
super("title");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(new GridLayout(rows,cols));
for(int i=0;i<label.length;i++){
label[i]= new JLabel(toString(i));
}
for(int i=0;i<button.length;i++){
for(int j=0;j<button.length;j++){
button[i][j]= new JButton(counter + "");
add(button[i][j]);
counter++;
}
}
}//end of constructor
public String toString(int k){
String s;
s=""+k;
return s;
}
}
You've been creating the buttons with the label toString() method name.

Using an Action Listener to change a JPanel's contents [duplicate]

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 :).

How do I display multiple JPanels with multiple layouts?

I've been working on this project for an assignment and I've been stuck on this problem. I new and don't understand much of the programming jargon so if someone could help explain why my program isn't working that would be great.
The programs purpose is to display a randomly generated matrix of 1's and 0's in a 10x10 layout and have some buttons on the top that have functions. I'm just stock on how to get everything to display.
Thanks in advance.
UPDATE:: Told providing all my code would help
public class Module5 extends JFrame {
private static JTextArea area = new JTextArea();
private static JFrame frame = new JFrame();
private static JPanel general = new JPanel();
private static JPanel buttons = new JPanel();
private static JPanel numbers = new JPanel();
private static JButton button0 = new JButton("Reset to 0");
private static JButton button1 = new JButton("Resset to 1");
private static JButton buttonReset = new JButton("Reset");
private static JButton quit = new JButton("Quit");
public static class Numbers extends JPanel {
public Numbers() {
area.setText(Integer.toString((int) Math.round(Math.random())));
this.add(area);
}
public void Module5(){
numbers.setLayout(new GridLayout(10, 10));
for (int i = 0; i < 100; i++) {
this.add(new Numbers());
}
}
}
public static void main (String[] args) {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 300);
frame.setVisible(true);
general.setLayout(new BoxLayout(general, BoxLayout.Y_AXIS));
general.add(buttons);
general.add(numbers);
buttons.add(button0);
buttons.add(button1);
buttons.add(buttonReset);
buttons.add(quit);
quit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
});
}
}
Since this does look like homework I'll give you some pointers but am not going to give you the code.
Move your constructor for Module5 out of the numbers class and into its own class. Also remove the void return type from this to make it a correct constructor.
Move the code in your main into the constructor for Module5. This is the main frame so when you build a new one it should be initialised here, not in main. And remove the setVisible call for now (this is addressed in number 6)
After doing 1 and 2, get rid of your frame variable, your Module5 is a JFrame so anything to do with frame can just be changed to the keyword this (meaning this Module5 object)
Also move the area variable to be within the Numbers class - otherwise every Number is essentially going to share the same text area and This is not what you want.
Don't have your variables as static they should not need to be.
Once this is all done make sure it is running on the Event Dispatch Thread by making your main method like this (the one piece of code I will give you)
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
Module5 mod5 = new Module5();
mod5.setVisible(true);
}
});
}

How to move shape across JPanel?

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();
}
});
}

JFrame freezes after calling getContentPane().removeAll()

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

Categories