Is there an easier way to shift 'older' components down when adding newer components (whenever a button is pressed)?

Jam :

I've tried looking for an answer to my question, but couldn't find anything similar. If it's already been asked, please link. Thanks in advance.

The layout of the main panel, mainPanel, is GridBagLayout. It has three buttons. Two of them are duds (for the purpose of this question). The middle button, butt2, creates a JPanel with other components in it every time butt2 is pressed.

Because butt2 is in the middle, and butt3 is directly below it, I have an int variable, tracker2, that tracks the gridy of butt2. Every time butt2 is pressed, I create a new JPanel that goes under butt2, increment tracker2, and then remove butt3 and add it below the newer component.

import java.util.List;
import java.util.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;

import javax.swing.*;

 public class Demo implements ActionListener 
     public static void main(String[] args) {
         Demo demo = new Demo();
     }

     private JFrame frame;
     private JPanel mainPanel;
     private JButton butt1, butt2, butt3;
     private GridBagConstraints gb;
     private List<JTextField> list;
     private int count, tracker2;

     public Demo() {
         frame = new JFrame("Demo");
         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         frame.setResizable(true);
         frame.setBounds(0, 0, 800, 800);
         list = new ArrayList<JTextField>();
         count = 0;
         tracker2 = 0;

         commence();
     }

     private void commence() {
         gb = new GridBagConstraints();
         gb.anchor = GridBagConstraints.FIRST_LINE_START;
         gb.weightx = 1;
         gb.insets = new Insets(50, 5, 0, 20);

         mainPanel = new JPanel();
         mainPanel.setBackground(Color.white);
         mainPanel.setLayout( new GridBagLayout() );

         butt1 = new JButton("One");
         butt1.setPreferredSize( new Dimension(100, 50) );
         // Add to panel
         gb.gridx = 0;
         gb.gridy = 0;
         mainPanel.add( butt1, gb);

         butt2 = new JButton("Two");
         butt2.setPreferredSize( new Dimension(100, 50) );
         butt2.addActionListener(this);
         // Add to panel
         gb.gridy++;
         tracker2 = gb.gridy;
         mainPanel.add( butt2, gb );

         butt3 = new JButton("Three");
         butt3.setPreferredSize( new Dimension(100, 50) );
         // Add to panel
         gb.gridy++;
         mainPanel.add( butt3, gb );

         frame.add(mainPanel);
         frame.setVisible(true);
         frame.repaint();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource().equals( butt2 )) {
            commence2();
        }
    }

    private void commence2() {
        gb.insets = new Insets( 0, 0, 0, 0 );
        list.add( new JTextField(30) );

        JLabel label = new JLabel("LABEL 2   ");
        label.setDisplayedMnemonic( KeyEvent.VK_N );
        label.setLabelFor( list.get(count) );

        JPanel panel = new JPanel( new FlowLayout(FlowLayout.LEFT, 10, 3));
        panel.setBackground( Color.white );
        panel.add(label);
        panel.add(list.get( count ));
        // Add to mainPanel
        tracker2++;
        gb.gridy = tracker2;
        mainPanel.add( panel, gb );
        updateFrame();
        // Increment count
        count++;

        frame.revalidate();
        frame.repaint();
    }

    private void updateFrame() {
        mainPanel.remove( butt3 );
        gb.insets = new Insets(50, 5, 0, 20);
        gb.gridy = tracker2 + 1;
        mainPanel.add( butt3, gb );
    }
}

Is there an easier way to do this or a Layout that automatically does this for me?

Thomas Behr :

Yes, there is an easier way. Instead of adding the new text fields to your mainPanel use an additional Container. E.g.

public class Demo2 implements ActionListener {
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override
      public void run() {
        new Demo2();
      }
    });
  }

  private JFrame frame;
  private JPanel textPanel;
  private JButton butt1, butt2, butt3;

  public Demo2() {
    frame = new JFrame("Demo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setResizable(true);
    frame.setBounds(0, 0, 800, 800);

    commence();
  }

  private void commence() {
    GridBagConstraints gb = new GridBagConstraints();
    gb.anchor = GridBagConstraints.FIRST_LINE_START;
    gb.weightx = 1;
    gb.insets = new Insets(50, 5, 0, 20);

    JPanel mainPanel = new JPanel();
    mainPanel.setBackground(Color.white);
    mainPanel.setLayout( new GridBagLayout() );

    butt1 = new JButton("One");
    butt1.setPreferredSize( new Dimension(100, 50) );
    // Add to panel
    gb.gridx = 0;
    gb.gridy = 0;
    mainPanel.add( butt1, gb);

    butt2 = new JButton("Two");
    butt2.setPreferredSize( new Dimension(100, 50) );
    butt2.addActionListener(this);
    // Add to panel
    gb.gridy++;
    gb.insets = new Insets(50, 5, 0, 0);
    mainPanel.add( butt2, gb );

    textPanel = new JPanel(new GridLayout(0, 1));
    // Add to panel
    gb.gridy++;
    gb.insets = new Insets(0, 5, 0, 20);
    mainPanel.add( textPanel, gb );

    butt3 = new JButton("Three");
    butt3.setPreferredSize( new Dimension(100, 50) );
    // Add to panel
    gb.gridy++;
    gb.insets = new Insets(50, 5, 0, 20);
    mainPanel.add( butt3, gb );

    frame.add(mainPanel);
    frame.setVisible(true);
    frame.repaint();
  }

  @Override
  public void actionPerformed(ActionEvent e) {
    if(e.getSource().equals( butt2 )) {
      commence2();
    }
  }

  private void commence2() {
    JTextField jtf = new JTextField(30);

    JLabel label = new JLabel("LABEL 2   ");
    label.setDisplayedMnemonic(KeyEvent.VK_N );
    label.setLabelFor( jtf );

    JPanel panel = new JPanel( new FlowLayout(FlowLayout.LEFT, 10, 3));
    panel.setBackground( Color.white );
    panel.add(label);
    panel.add( jtf );

    // Add to mainPanel
    textPanel.add( panel );
    textPanel.revalidate();

    frame.revalidate();
    frame.repaint();
  }
}

In the above code, textPanel serves as container for the new text fields.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=104320&siteId=1