0

Given an array of "modules" which are instances of various different JPanel extensions, how can I "run" each of them in sequence, so that the (i+1)st one opens when the ith one closes?

I'm creating a psychology experiment based on inherited code. The inherited code implements a number of experimental tasks, each as a separate class. Each of these classes extends JPanel and has a method "go" which, when called, creates a JFrame and uses it to display the contents of the module. So, for instance, I have classes like:

public class Module_1 extends JPanel implements MouseListener, KeyListener {
    ...
    protected JFrame frame;
    ...
    public void go() {
        frame = new JFrame();
        ...
    }
    ...
}
public class Module_2 extends JPanel implements MouseListener, KeyListener {
    ... 
    // same general format as above
    ...
}

Then I have a series of modules, each one belonging to one of the above classes. I want to run go() from the first module, which will create a JFrame. When this JFrame is closed, I want to run go() from the module, and so on. What's the best way to do this?

My approach was to add a callback to each module, e.g.

public interface Callback {
    public void call();
}
public class Module_1 extends JPanel implements MouseListener, KeyListener {
    ...
    protected JFrame frame;
    ...
    public void go() {
        frame = new JFrame();
        ...
    }
    public void setCallback(Callback c) {
        frame.addWindowListener( new java.awt.event.WindowAdapter() {
            @Override
            public void windowClosing( java.awt.event.WindowEvent windowEvent ) {
                c.call();
            }
        });
    }
    ...
}
// and do the same for the other modules

Then, I attempted to create a utility which would take an array of modules and run through them in the manner described:

public class Panel_sequencer {

    private Object[] modules;

    public Panel_sequencer( Object[] Ms ) {
        this.modules = Ms.clone();
    }

    private void iterate( int idx ) {
        if ( idx>=this.modules.length ) {
            return;
        } else {
            Object M = this.modules[idx];
            M.go();
            M.setCallback( new Callback() {
                public void call() {
                    System.out.println("Completed module "+idx);
                    iterate( idx+1 );
                }
            });
        }
    }

}

However, this doesn't work because go() isn't defined for type Object. Is there a way around this? Or should I be using a different approach entirely?

baixiwei
  • 1,009
  • 4
  • 20
  • 27
  • Something in me wants to say bad practice here... – DreadHeadedDeveloper Oct 20 '14 at 15:56
  • 2
    Write a `Module` interface that specifies the `go()` method, and then have a `Module[]` array instead of `Object[]`. – khelwood Oct 20 '14 at 15:57
  • @DreadHeadedDeveloper, are you referring to the inherited part or to the thing I am trying to do? – baixiwei Oct 20 '14 at 16:17
  • 1
    The thing you are trying to do, several JFrames, even if they are one at a time, for some reason says bad practice to me. I can't prove it though, but I feel updating a JLabel, or something would be a better alternative – DreadHeadedDeveloper Oct 20 '14 at 16:19
  • 3
    Consider `CardLayout`, for [example](http://stackoverflow.com/a/5655843/230513). – trashgod Oct 20 '14 at 16:23
  • I think I agree with the intuition but wouldn't avoiding the use of several JFrames require substantial revision to the inherited code? – baixiwei Oct 20 '14 at 16:51
  • Inherited from what? Rewriting code for card layout from multiple frames is simple. You only need to modify the top container. – user1803551 Oct 20 '14 at 17:57
  • @user1803551 from your reply I understand that yes, the revisions proposed by DreadHeadedDeveloper and trashgod would require changing the individual module classes to extend a different class from what they do now, correct? It seems to me that this change could risk breaking some part of the code that I inherited from the previous person working on the project, so such changes are to be avoided if possible. Is there some reason this wouldn't be a concern? – baixiwei Oct 20 '14 at 18:46
  • 1
    If you have the `JPanel`s (modules) ready, instead of adding them to different `JFrame`s, add them to one which uses the `CardLayout`. Then instead of closing and opening frames, switch cards. Do you need code to demonstrate this? – user1803551 Oct 20 '14 at 18:58
  • To specifically answer your questions: (1) trashgod (as usual) and DreadHeadedDeveloper are correct. (2) You don't need to extend a different class for your modules. (3) I don't know exactly what could break and what not, but I would say that this transition shouldn't be a concern. – user1803551 Oct 20 '14 at 19:00
  • @user1803551, yes, that would be helpful ... I tried to figure it out but it was kind of opaque to me. (New Java programmer here.) – baixiwei Oct 20 '14 at 19:59
  • See [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/q/9554636/418556) – Andrew Thompson Oct 20 '14 at 20:51
  • Then look at trashgod's examples of card layout. If you still can't get it to work I'll port something. – user1803551 Oct 20 '14 at 23:44

0 Answers0