views:

476

answers:

3

Hi all. I'm developing a sim game based on Theme Hospital, which is quite an old game. I've made lots of progress on the underlying workings, however now I am coming to the GUI elements, which I haven't done alot of before. I am still rather new to java. The effect I am trying to create is like shown here...

http://www.tubechop.com/watch/18438

Click on a button, opens up a panel with tabs to select from different selections, and then click a button to build a room. I believe for the "tabs" I can use a card layout? For the actual building of rooms, I am pretty much sorted. The main problem I have right now, is getting the panel to open up on the click of a button.

At current, I have 1 JFrame and 2 JPanels ontop, the main game panel and the control panel with a few buttons.

Can anyone show me some simple example of how I would do such a thing? I know its probably really simple, and I bet some of you could even write the code off the top of your head, but I am new to java, and have been taught more about the logical elements of programming so far rather than how to build a more complex multi layered GUI like required in a game.

I know it's an ambitious project, but I have come a long way, and have even implemented custom path finding using A*, which I'm happy about (All thanks to you people here at StackOverflow!)

Thank you in advance for your help.

A: 

The main problem I have right now, is getting the panel to open up on the click of a button.

You don't open up another panel. You would probably use a JDialog that contains another panel. You could then use a CardLayout or you could use a JTabbedPane on the dialog. The design choices are up to you.

I suggest you start by reading the Swing tutorial for examples of all the components. I can't really offer any advice on the graphics of the program. For that you need to start asking specific questions. But building dialogs, with panels and components is straight forward.

camickr
A: 

The button processing is pretty easy. You need to have a class implement the ActionListener interface, and it needs to be registered with your button. You can see some pretty clear examples here.

For the panels that you want to bring up, it looks like what you are looking for can be found within the Root Pane framework built into the top-level Swing containers. Here is a tutorial.

The Root Pane framework includes the Glass Pane, which is a clear pane that sits on the top of the z-order stack of the top-level components. You also have the Layered Pane, which might suit your needs a bit more. There is a tutorial for that as well.

akf
+2  A: 

JDialogs would work, but they're going to pop up new top level windows over your game window. You could implement your main game display and control panel as the background of a JDesktopPane(which extends JLayeredPane), and could make the pop ups JInternalFrames.

Contrived (but working) example:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentAdapter;
import java.awt.event.ActionListener;
import java.text.NumberFormat;

public class DesktopTest extends JFrame {

private JDesktopPane desktop;
private JPanel background;
private JInternalFrame firstFrame;
private JInternalFrame secondFrame;

public DesktopTest() {
    super("DesktopTest");

    desktop = new JDesktopPane();
    setContentPane(desktop);

    background = new JPanel(new BorderLayout());
    JToolBar toolbar = new JToolBar();
    toolbar.add(new AbstractAction("1") {

        public void actionPerformed(ActionEvent actionEvent) {
            firstFrame.setVisible(true);
        }
    });

    toolbar.add(new AbstractAction("2") {

        public void actionPerformed(ActionEvent actionEvent) {
            secondFrame.setVisible(true);
        }
    });
    AddPanel addPanel = new AddPanel();
    background.add(addPanel, BorderLayout.CENTER);
    background.add(toolbar, BorderLayout.SOUTH);
    addComponentListener(new ComponentAdapter() {

        public void componentResized(ComponentEvent componentEvent) {
            background.setSize(desktop.getSize());
            background.revalidate();
            background.repaint();
        }

        public void componentShown(ComponentEvent componentEvent) {
            background.setSize(desktop.getSize());
            background.revalidate();
            background.repaint();
        }
    });
    desktop.add(background);

    firstFrame = new TermFrame("First Term", "Update First Term: ", addPanel) {

        protected int getValue() {
            return addPanel.getFirst();
        }

        protected void update(int value) {
            addPanel.setFirst(value);
        }
    };
    firstFrame.pack();
    firstFrame.setBounds(10, 10, 200, 150);
    desktop.add(firstFrame);

    secondFrame = new TermFrame("Second Term", "Update Second Term: ", addPanel){

        protected int getValue() {
            return addPanel.getSecond();
        }

        protected void update(int value) {
            addPanel.setSecond(value);
        }
    };
    secondFrame.pack();
    secondFrame.setBounds(200, 200, 200, 150);
    desktop.add(secondFrame);

}

public static void main(String[] args) {
    JFrame f = new DesktopTest();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    f.setSize(400, 400);
    f.setLocationRelativeTo(null);
    f.setVisible(true);
}

static class AddPanel extends JPanel {
    private JLabel first;
    private JLabel second;
    private JLabel result;

    public AddPanel() {
        first = new JLabel("0");
        second = new JLabel("0");
        result = new JLabel("0");

        Box vertical = Box.createVerticalBox();
        vertical.add(Box.createVerticalGlue());
        Box horizontal = Box.createHorizontalBox();
        horizontal.add(Box.createHorizontalGlue());
        horizontal.add(first);
        horizontal.add(new JLabel("+"));
        horizontal.add(second);
        horizontal.add(new JLabel("="));
        horizontal.add(result);
        horizontal.add(Box.createHorizontalGlue());
        vertical.add(horizontal);
        vertical.add(Box.createVerticalGlue());

        setLayout(new BorderLayout());
        add(vertical, BorderLayout.CENTER);
    }

    public void setFirst(int i) {
        first.setText(Integer.toString(i));
        updateResult();
    }

    public int getFirst() {
        return Integer.parseInt(first.getText());
    }

    public void setSecond(int j) {
        second.setText(Integer.toString(j));
        updateResult();
    }

    public int getSecond() {
        return Integer.parseInt(second.getText());
    }

    private void updateResult() {
        int i = Integer.parseInt(first.getText());
        int j = Integer.parseInt(second.getText());
        result.setText(Integer.toString(i + j));
        revalidate();
    }
}

static abstract class TermFrame extends JInternalFrame {

    protected AddPanel addPanel;
    private JFormattedTextField termField;

    public TermFrame(String title, String message, AddPanel addPanel) {
        super(title, true, true, true);
        this.addPanel = addPanel;
        NumberFormat format = NumberFormat.getNumberInstance();
        format.setMaximumFractionDigits(0);
        termField = new JFormattedTextField(format);
        termField.setColumns(3);
        termField.setValue(getValue());

        JPanel content = new JPanel(new FlowLayout());
        content.add(new JLabel(message));
        content.add(termField);
        JButton apply = new JButton("apply");
        apply.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent actionEvent) {
                Integer value = Integer.parseInt(termField.getText());
                update(value);
            }
        });
        content.add(apply);
        setContentPane(content);

        setDefaultCloseOperation(JInternalFrame.HIDE_ON_CLOSE);
    }

    protected abstract int getValue();

    protected abstract void update(int value);


}
}
Nate
This looks to me exactly what I'm looking for. Thanks.Anyone got any comments on this? Is it good or bad practice this way, or just up to individual preference?
Relequestual
Hi Nate. I am having some issues implementing it into my project.I have probably done some very silly mistake, but have been tweaking for about 2-3 hours now, so thought it time to ask before I muck it up again... here is a link to what I consider the relevant bits of code... http://snipt.org/kpJ Thanks in advance
Relequestual
My bad, I defined the mainPane twice. Progress! :) now having some other funny issue but hopefully I'll get it!
Relequestual
Sorry - wasn't on earlier, but good to know you got it to work though. :)
Nate
Thanks ok. Yeh its nearly working, just something seems to cover up most other stuff when it makes the internal frame visible... I made a quick video here to show you exactly what I mean.http://is.gd/1wVIKThanks again for your help! :)
Relequestual
Could you post your current code somewhere? It looks like there might be some extra component added somewhere that gets Z-ordered to the top. But it would be easier to find if I could see all the code.
Nate
There's quite a lot of classes, so I uploaded all the code that I thought was relevant. I shall re check and upload some more code...http://snipt.org/kploI know there's a heck of a lot of code here. Thanks again for your help! I will make sure your name goes down in the thanks list on this project!
Relequestual
Made a further video for you after I discovered this. http://screenjel.ly/bdvB7pH7YO8May be getting a little sleepy. Still, trying to solve the issue. Thanks again for your help.
Relequestual
further update, removed the scroll panel and it seemed to work fine. I mean I made the game panel be added to the JFrame and commented out the scroll panel. I think I need the scroll panel though in the long run :S
Relequestual
I believe the problem is with this line -jScrollPane1.add(hospitalGamePanel);it should be -jScrollPane1.setViewportView(hospitalGamePanel);
Nate
Fantastic! works brilliantly now! :) Implementing auto scroll when mouse is at the screens edge. Thanks again Nate!
Relequestual
Could you post a picture of the result?
Daniel
I have already made a little video of it. If you click on the screenhel.ly link in these comments, and then click on my user, watch the latest video. This is everything I have done visually so far.
Relequestual