1

When I run this class(Try class), it calls the Stacker class completely(with full functions), but when I use other class(I used JFrame with button that has actionlistener that calls Stacker class) to run this(Stacker class), the JFrame(Stacker class) will pop-up but empty and I can't close the program.

I tried to run this(Stacker) from other class like this:

public class Try {

    /**
     * @param args
     */
    public static void main(String[] args) {

        run();

    }

    public static void run(){
        new Stacker();
    }

}

The Stacker class ran fully(I can interact with it). But when I tried to call the stacker class from an actionlistener of a button in JFrame, it's blank and can't be closed.

Please help me.

here are my codes for the Stacker class:

import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class Stacker  extends JFrame implements KeyListener {

    int iteration = 1;
    static double time = 200;
    static int last = 0;
    static int m = 10;
    static int n = 20;
    JButton b[][];
    static int length[] = {5,5};
    static int layer = 19;
    static int deltax[] = {0,0};
    static boolean press = false;
    static boolean forward = true;
    static boolean start = true;
    JPanel panel;

    public static void main (String[] args) {
        Stacker stack = new Stacker();
        stack.setVisible(true);
    }

    public Stacker() {
        panel = new JPanel();
        panel.setLayout(new GridLayout(20,10));

        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        b = new JButton [m][n];

        for (int y = 0;y<n;y++) {
            for (int x = 0;x<m;x++) {
                b[x][y] = new JButton(" ");
                b[x][y].setBackground(Color.white);
                b[x][y].setBorderPainted(false);
                panel.add(b[x][y]);
                b[x][y].setEnabled(true);
            }//end inner for
        }
        setSize(390, 560);
        setLayout(new GridBagLayout());
        add(panel);
        setFocusable(true);
        addKeyListener(this);
        pack();
        setVisible(true);
        go();
    }

    public void go() {
        int tmp = 0;
        Component temporaryLostComponent = null;
        do {
            if (forward == true) {
                forward();
            } else {
                back();
            }
            if (deltax[1] == 10-length[1]){
                forward = false;
            } else if (deltax[1] == 0){
                forward = true;
            }
            draw();
            try {
                Thread.sleep((long) time);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }while(press == false);
        if (layer>12) {
            time= 150-(iteration*iteration*2-iteration); 
        } else {
            time = time - 2.2;
        }
        iteration++;
        layer--;
        press = false;
        tmp = check();
        length[0] = length[1];
        length[1] = tmp;
        if (layer == -1) {
            JOptionPane.showMessageDialog(temporaryLostComponent, "Congratulations! You beat the game!");
        }
        if (length[1] <= 0) {
            JOptionPane.showMessageDialog(temporaryLostComponent, "Game over! You reached line "+(18-layer)+"!");
            System.exit(0);
        }
        last = deltax[1];
        start = false;
        go();
    }

    public int check() {
        if (start == true) {
            return length[1];
        } else if (last<deltax[1]) {
            if (deltax[1]+length[1]-1 <= last+length[0]-1) {
                return length[1];
            } else {
                return length[1]-Math.abs((deltax[1]+length[1])-(last+length[0]));
            }
        } else if (last>deltax[1]) {
            return length[1]-Math.abs(deltax[1]-last);
        } else {
            return length[1];
        }
    }

    public void forward() {
        deltax[0] = deltax[1];
        deltax[1]++;
    }

    public void back() {
        deltax[0] = deltax[1];
        deltax[1]--;
    }

    public void draw() {
        for (int x = 0;x<length[1];x++) {
            b[x+deltax[0]][layer].setBackground(Color.white);
        }
        for (int x = 0;x<length[1];x++) {
            b[x+deltax[1]][layer].setBackground(Color.BLUE);
        }
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            press = true;
        }
    }

    @Override
    public void keyReleased(KeyEvent arg0) {
        // TODO Auto-generated method stub
    }

    @Override
    public void keyTyped(KeyEvent arg0) {
        // TODO Auto-generated method stub
    }
}
  • 1
    Moreover, `stack.setVisible(true);` lies in the `main` method of `Stacker` class, which you never called when calling the constructor from some another class, so put this line at the end of the constructor of the `Stacker` class :-) – nIcE cOw Sep 22 '13 at 12:46
  • so you mean I'll put [Stacker stack = new Stacker(); stack.setVisible(true);] inside the constructor? delete it in the main or just add on the constructor? – Jackneil De Las Alas Sep 22 '13 at 13:23
  • What I mean is, inside the `run()` method of `Try` class, do what you doing in the `main` method of the `Stacker` class. Create an Object and call `setVisible()` using that reference. Or else leave everything as is, just add `setVisible()` to the end of the constructor of the `Stacker` class. Now inside `main` or `run` methods just create an object `new Stacker()` now everything will work :-) – nIcE cOw Sep 22 '13 at 13:27
  • As I understand, your helping me to run the `stacker class` from the `try class`. If I'm right, the `try class` is my example for other classes that can call the `stacker class`, I'm asking for a JFrame class with button that can call the `stacker class`. – Jackneil De Las Alas Sep 22 '13 at 13:42
  • 1
    Then instead of creating multiple `JFrame`s you should be focusing on simply changing the `JPanel` at the click of the `JButton` to change it to a new `View` using `CardLayout` as shown in this [example](http://stackoverflow.com/a/9349137/1057230) :-) – nIcE cOw Sep 22 '13 at 15:21
  • One related [example](http://stackoverflow.com/a/9443609/1057230) :-) – nIcE cOw Sep 22 '13 at 16:42
  • Ok. I'll try that one. I'll just update if it worked. – Jackneil De Las Alas Sep 23 '13 at 01:19

3 Answers3

2

Your do-while loop and thread sleep look suspicious in that it is running on the Swing event thread tying it up. The problem is that these longer running tasks lock the Swing Event Dispatch Thread, or EDT, the one thread that is responsible for all Swing graphics and user interactions, preventing your application from drawing itself and all of its widgets and prevents the application from responding to any user input.

Likely the application ran in isolation because the issues that I identified above ran off of the EDT, and doing this code wise is one possible solution to your problem, but I'm betting that there are better solutions available that we can help you with if you tell us more about the details of your problem.

Also you appear to be using recursion in a dangerous way having the go method call itself. Can't really say more since I'm on a cell phone.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • I can't really modify the codes thoroughly because i just got that from the net. All I can make is to have menus before playing that game (stacker class). :( Also I'm confused on the "program more event driven and state based" coz I'm still so newbie. – Jackneil De Las Alas Sep 22 '13 at 10:41
  • 2
    *"I can't really modify the codes thoroughly because i just got that from the net."* It seems you need to put them back where you found them an *learn Java.* SO is not a 'fix this code I found' site. – Andrew Thompson Sep 22 '13 at 10:45
  • 1
    @JackneilDeLasAlas: don't try to salvage bad code. Why not instead write your own good code. – Hovercraft Full Of Eels Sep 22 '13 at 10:53
  • I'm sorry for that but I've left no choice but to ask for professional help for my final project. Coz our farthest topic is about guis. I can't afford to fail my subject. – Jackneil De Las Alas Sep 22 '13 at 10:55
  • @JackneilDeLasAlas: final project and grade have nothing to do with this. Your horse is dead. You can try beating it all you want but it will still be dead. – Hovercraft Full Of Eels Sep 22 '13 at 12:32
  • @Hovercraft Full Of Eels: I think I got your explenation. The codes are so fully loaded(can't find the right term) so running it from other JFrame causes the Stacker class to hang up? Preventing the objects to load up? – Jackneil De Las Alas Sep 22 '13 at 13:54
  • @JackneilDeLasAlas: not quite "fully loaded". It's more about what thread your code is running on. Also as an aside, a JFrame will usually not display another JFrame. A JDialog perhaps, but not a JFrame. – Hovercraft Full Of Eels Sep 22 '13 at 14:06
  • Really? because my menu is jframe then when i click start another jframe pops up for background then when already chose background, another jframe pops up for difficulty then that the time I'll call the stacker class. – Jackneil De Las Alas Sep 22 '13 at 14:20
  • @JackneilDeLasAlas: really. A JFrame is built to be the base window of an application. What you are describing are dialog Windows and these should be implemented as JDialogs, especially if the dialog window should be modal. – Hovercraft Full Of Eels Sep 22 '13 at 14:23
  • I want to show you the sequence of my project but I'm still below 10 reputation. :( I tried to put this: `EventQueue.invokeLater(new Runnable() { public void run() { try { Stacker frame = new Stacker(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } });` instead of the `Stacker stack = new Stacker(); stack.setVisible(true);` but it wont run. – Jackneil De Las Alas Sep 22 '13 at 14:37
1

Firstly, I would replace:this.setDefaultCloseOperation(DISPOSE_ON_CLOSE); with the following:

this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

as DISPOSE_ON_CLOSE is a static/class variable.

In fact, I am surprised that your IDE did not pick that up (unless, you aren't using an IDE).

blackpanther
  • 10,998
  • 11
  • 48
  • 78
-1
SwingWorker worker = new SwingWorker<Void, Void>() {

     @Override
       protected Void doInBackground() throws Exception {
               Stacker stack = new Stacker();
               stack.setVisible(true);
              return null;
           }
    };
    worker.execute();

after using this method, when I call Stacker class from another JFrame, the game executes perfectly. Just like when calling Stacker class from Try class.

Thank you for all the responses I had. :D

  • Sorry but your answer is wrong and is a set up for disaster since you're making Swing calls from a background thread. This type of code might work 8 out of 10 times, but will fail when most needed. – Hovercraft Full Of Eels Sep 24 '13 at 10:54