1

So I have a layout made with buttons,textfields, and labels. A user is supposed to put input into the textfields. When he hits a button, I want it so that the input is cleared and a new "page" is shown with the layout i have made. The user can input as much information into new "pages" as he wants until he hits an "finished" button. In short, I want to switch between panels or frames (i dont know which, probably panels??). Now, I was thinking of using card layout to do this but since i'm reading user input it wouldn't really make sense since cardlayout is made based on a predetermined amount of panels and what will be in the panels. Since I won't know when the user is "finished", I won't know how many panels to use.

Anyways, I'm just a beginner with GUI so any help would be great!

dic19
  • 17,821
  • 6
  • 40
  • 69
user3408559
  • 67
  • 1
  • 9
  • will your buttons always be visible? – mig Mar 12 '14 at 23:59
  • yes. im' not sure what you're asking though.. – user3408559 Mar 13 '14 at 00:08
  • sorry for not being clear, let me start rather with are you using only one panel in your layout or multiple panels (example: 1 to hold your buttons, one to hold your textfields/labels) inside one frame? – mig Mar 13 '14 at 00:11
  • im using a base panel with a border layout. my buttons are in a panel with a flow layout and my labels\textfields are in a panel with a gridbag layout. – user3408559 Mar 13 '14 at 00:12
  • 1
    Start by taking a look at [How to use CardLayout](http://docs.oracle.com/javase/tutorial/uiswing/layout/card.html) – MadProgrammer Mar 13 '14 at 00:20
  • @MadProgrammer wow thank you for that link! i feel ashamed for trying to use cardlayout without knowing it's full functionality such as the next,prev methods. – user3408559 Mar 13 '14 at 00:38

2 Answers2

2

Now, I was thinking of using card layout to do this but since i'm reading user input it wouldn't really make sense since cardlayout is made based on a predetermined amount of panels and what will be in the panels. Since I won't know when the user is "finished", I won't know how many panels to use.

You can dinamically add components to CardLayout on next button's click. If all the pages have the same structure you can have a class for those pages and add a new one every time next button is pressed. When finish button is pressed do something with all those pages iterating over the panel (with CardLayout) components. Take a look to Container.getComponents() method. You don't even need to keep any kind of array nor list because the container already do so.

Example

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class Demo {

    private void createAndShowGUI() {

        final JPanel cardPanel = new JPanel(new CardLayout());        
        cardPanel.add(new Page(), "1");

        final JButton nextButton = new JButton("Next");
        nextButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                cardPanel.add(new Page(), String.valueOf(cardPanel.getComponentCount() + 1));
                CardLayout layout = (CardLayout)cardPanel.getLayout();
                layout.next(cardPanel);
            }
        });

        final JButton finishButton = new JButton("Finish");
        finishButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                nextButton.setEnabled(false);
                for(Component comp : cardPanel.getComponents()) {
                    if(comp instanceof Page) {
                        Page page = (Page)comp;
                        page.printData();
                    }
                }
            }
        });

        JPanel buttonsPanel = new JPanel();
        buttonsPanel.add(nextButton);
        buttonsPanel.add(finishButton);

        JFrame frame = new JFrame("Demo");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(cardPanel, BorderLayout.CENTER);
        frame.getContentPane().add(buttonsPanel, BorderLayout.SOUTH);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    class Page extends JPanel {

        final private JTextField data;

        public Page() {
            super();
            add(new JLabel("Please add some info:"));
            data = new JTextField(20);
            add(data);
        }

        public void printData() {
            System.out.println(data.getText());
        }

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {                
                new Demo().createAndShowGUI();
            }
        });
    }
}
dic19
  • 17,821
  • 6
  • 40
  • 69
  • Wow, thank you! I noticed that the actionPerformed method was inside the parameter of nextButton.addActionListener. I did not know this was possible. If you don't mind, could you please tell me what this is called or perhaps provide me a link where I could read up on it? Much appreciated! – user3408559 Mar 13 '14 at 00:59
  • You're welcome. It's actually an anonymous inner class (google for that). It's also exemplified in [this answer](http://stackoverflow.com/questions/22093911/adding-actionlisteners-and-calling-methods-in-other-classes/22094339#22094339). If this answer is good enough for you then don't forget to accept it: [How does accepting an answer work?](http://meta.stackexchange.com/a/5235) – dic19 Mar 13 '14 at 01:26
  • Sorry to bug you again, but now I want to add a prev button. As far as I'm concerned, just having "layout.previous(___);" in the actionPerformed method body should work, but when I run my program and click the prev button, nothing happens. What am I doing wrong? – user3408559 Mar 13 '14 at 01:49
  • @user3408559 that's weird. You're righ it should work. If post your new code in a new question I'll take a look. :) – dic19 Mar 13 '14 at 02:03
  • Sure thing, I just posted the question. – user3408559 Mar 13 '14 at 02:30
0

As far as I understand from your description you do not need multiple panels. I am assuming that you have some sort of object hierarchy for your model layer. So, let's say you use those input values to create AnObject objects.

You can create an ArrayList<AnObject> in your top class. And as user inputs and clicks done you just create one more AnObject with given input and add it to the ArrayList you defined in top class.

BTW, you can also define ArrayList whereever it is reachable. But you must think carefully, to keep your data persistent. If the object of the class that you defined ArrayList is "gone", your data is also "gone". I think this should be clear enough.

The next step is just trivially clearing out those input fields.

This is the most straightforward way, it may not be the smartest way to do that depending on your use case. But it would give you an idea for what to look and learn for.