1

I am almost certain this question was asked before here: Java Swing: How to change GUI dynamically , but I seem to just have some fundamental misunderstanding in how it works.

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;

public class JTest extends JFrame
{
  public static void main(String[] args)
  {
    JTest t = new JTest();
  }

  Container pane;

  public JTest()
  {
    setSize(500,500);
    setTitle("JTest");
    setDefaultCloseOperation(EXIT_ON_CLOSE);
    pane = getContentPane();
    pane.setLayout(new GridLayout(1,2));
    JButton old = new JButton("old");
    old.addActionListener(new OldButton());
    pane.add(old);
    JScrollPane scroll = new JScrollPane(new JTextArea(50,20));
    pane.add(scroll);

    setVisible(true);
  }

  private class OldButton implements ActionListener
  {
    public void actionPerformed(ActionEvent e)
    {
      pane.setLayout(new GridLayout(1,2));
      JButton old = new JButton("new");
      old.addActionListener(new NewButton());
      pane.add(old);
      JScrollPane scroll = new JScrollPane(new JTextArea(50,20));
      pane.add(scroll);
      pane.validate();
    }
  }

  private class NewButton implements ActionListener
  {
    public void actionPerformed(ActionEvent e)
    {

      pane.setLayout(new GridLayout(1,2));
      JButton old = new JButton("old");
      old.addActionListener(new OldButton());
      pane.add(old);
      JScrollPane scroll = new JScrollPane(new JTextArea(50,20));
      pane.add(scroll);
      pane.validate();
    }
  }  
}

This code should replace the preexisting layout with a new one anytime the button in the corner is pressed, but instead, it just adds the new layout to the frame. Can someone tell me what I'm doing wrong?

EDIT:

Adding some information. A picture for reference:

picture

I'm making a set of components like this inside the scroll pane. whenever I press the "Make new field" button, I want it to add a "field" (the name of the field followed by a textarea or some such) to the set in that scrollpane. This means changing the layout of the area inside the scrollpane to include the new field.

Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
  • If all you want your button to do is to change the layout, then your ActionListener should do what trashgod recommends in his answer: change the container's layout and then tell the layout manager to re-layout its components. He recommends that you call `validate()` on the container, but this has been changed to `revalidate()` more recently, but that's it. Why are you not doing this? And why is your ActionListener doing the other things? – Hovercraft Full Of Eels Jan 12 '18 at 20:33
  • If you need to change components that are shown, then use a CardLayout. If you want to change the button, then either change its text, or its ActionListener or best of all, its Action. Please clarify **exactly** what it is you want to have happen. – Hovercraft Full Of Eels Jan 12 '18 at 20:37
  • @Hovercraft What I want to do exactly is create a list of components on the frame. when a button is pressed, I want to be able to add or remove an undetermined number of components to/from the frame. I'm pretty sure that requires either replacing or changing the layout, but every way I've tried just creates a weird duplicate layout. – goinginsane Jan 12 '18 at 21:02
  • Please enumerate more specifically what you mean by "create a list of components" because the details matter. Consider editing your question with this information. – Hovercraft Full Of Eels Jan 12 '18 at 21:04

2 Answers2

1

OK -- so it looks like what you want to do (and please correct me if I'm wrong) is to add a new component to a JPanel that is displayed within a JScrollPane. If so, then you do not want to change or swap layouts, and you certainly don't want to keep adding new JScrollPanes. Instead consider doing:

  • Create one JScrollPane and add to your GUI. Don't re-add this as you'll only need one.
  • add a JPanel to the JScrollPane's viewport that uses a layout that allows multiple components to be easily added to it. Perhaps a GridLayout or a BoxLayout, depending on what you need.
  • Also consider not adding the above JPanel directly to the viewport but rather adding it to another JPanel, one that uses BorderLayout, adding the first JPanel to the BorderLayout-using JPanel's BorderLayout.PAGE_START position, and then add this to the JScrollPane's viewport. This way the first JPanel won't stretch to fill the viewport initially.
  • Then in your button's ActionListener, add your components to the first JPanel by calling .add(...) on it, and then call revalidate() and repaint() on that first JPanel to layout the newly added components and repaint the JPanel and its contents.
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
0

Ok, so it turns out this wasn't a layout problem at all. I had failed to realize that setting a new layout doesn't cause the previous layout's components to disappear, you have to remove them before adding the new components. That's why I was getting duplication.

Thanks for pointing me in the right direction, though.