2

I just started using Java Swing, and I was going through the following post: Dynamic fields addition in java/swing form. I implement the code in this post with some modification, and it worked fine. As mentioned in the post, JPanel is not resizing itself when we add more rows. Can someone throw more light on this issue with easy to understand explanation that how can we resize JPanel as soon as we hit +/- button? Here is the code :

Row class

import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;

@SuppressWarnings("serial")
public class Row extends JPanel {

    private JTextField quantity;
    private JTextField item;
    private JTextField price;
    private JButton plus;
    private JButton minus;
    private RowList parent;

    public Row(String initialQuantity, String initalPrice, String initialItem, RowList list) {
        this.parent = list;
        this.plus = new JButton(new AddRowAction());
        this.minus = new JButton(new RemoveRowAction());
        this.quantity = new JTextField(10);
        this.item = new JTextField(10);
        this.price = new JTextField(10);
        this.quantity.setText(initialQuantity);
        this.price.setText(initalPrice);
        this.item.setText(initialItem);
        add(this.plus);
        add(this.minus);
        add(this.quantity);
        add(this.item);
        add(this.price);
    }

    public class AddRowAction extends AbstractAction {

        public AddRowAction() {
            super("+");
        }

        public void actionPerformed(ActionEvent e) {
            parent.cloneRow(Row.this);
        }
    }

    public class RemoveRowAction extends AbstractAction {

        public RemoveRowAction() {
            super("-");
        }

        public void actionPerformed(ActionEvent e) {
            parent.removeItem(Row.this);
        }
    }

    public void enableAdd(boolean enabled) {
        this.plus.setEnabled(enabled);
    }
    public void enableMinus(boolean enabled) {
        this.minus.setEnabled(enabled);
    }
}

RowList class

    import java.util.ArrayList;
    import java.util.List;

    import javax.swing.JButton;
    import javax.swing.JLabel;
    import javax.swing.JPanel;

    @SuppressWarnings("serial")
    public class RowList extends JPanel{
        private List<Row> rows;

        public RowList() {
            this.rows = new ArrayList<Row>();
            Row initial = new Row("1","0.00","", this);
            //addHeaders();
            //addGenerateBillButton();
            addItem(initial);
        }

        public void addHeaders(){
            JLabel qty = new JLabel("Quantity");
            //qty.setBounds(10, 0, 80, 25);
            add(qty);
            JLabel item = new JLabel("Item");
            //item.setBounds(70, 0, 80, 25);
            add(item);
            JLabel price = new JLabel("Price");
            //price.setBounds(120, 0, 80, 25);
            add(price);
        }

        public void addGenerateBillButton(){
            JButton billGenerationButton = new JButton("Generate Bill");
            add(billGenerationButton);
        }

        public void cloneRow(Row row) {
            Row theClone = new Row("1","0.00","", this);
            addItem(theClone);
        }

        private void addItem(Row row) {
            rows.add(row);
            add(row);
            refresh();
        }

        public void removeItem(Row entry) {
            rows.remove(entry);
            remove(entry);
            refresh();
        }

        private void refresh() {
            revalidate();
            repaint();
            if (rows.size() == 1) {
                rows.get(0).enableMinus(false);
            }
            else {
                for (Row e : rows) {
                    e.enableMinus(true);
                }
            }
        }
    }

Main class

import javax.swing.JFrame;

public class Main {

    public static void main(String[] args) {
        JFrame frame = new JFrame("Enter Items");
        RowList panel = new RowList();
        frame.getContentPane().add(panel);
        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
 }
Community
  • 1
  • 1
JackSparrow
  • 187
  • 1
  • 2
  • 15
  • For better help sooner, post an [MCVE](http://stackoverflow.com/help/mcve) (Minimal Complete Verifiable Example). From the sounds of it, the OP on the quoted question chose buggy code over the better answer of camickr.. – Andrew Thompson Nov 06 '14 at 05:46
  • 1
    after adding/removing just call revalidate(); repaint() of the container pane – StanislavL Nov 06 '14 at 06:07
  • it appears this has no effect :( – JackSparrow Nov 06 '14 at 06:10
  • 1
    Actually, the panel **does try to resize itself**. The issue is simply that a window does not resize itself automatically, so the new rows are outside visible area. If you place the panel inside a `JScrollPane`, you'll see it grow automatically (though as the layout is `FlowLayout`, the "rows" will be added horizontally). – kiheru Nov 06 '14 at 08:20
  • 1
    For [example](http://stackoverflow.com/a/5760093/230513). – trashgod Nov 06 '14 at 10:16

2 Answers2

1

You can call the pack() of the frame again.

Try this: Add this in your Row class

    public class AddRowAction extends AbstractAction
    {

        public AddRowAction()
        {
            super("+");
        }

        public void actionPerformed(ActionEvent e)
        {
            parent.cloneRow(Row.this);

            ((JFrame) SwingUtilities.getRoot(parent)).pack(); // <--- THIS LINE
        }
    }

    public class RemoveRowAction extends AbstractAction
    {

        public RemoveRowAction()
        {
            super("-");
        }

        public void actionPerformed(ActionEvent e)
        {
            parent.removeItem(Row.this);

            ((JFrame) SwingUtilities.getRoot(parent)).pack(); // <--- THIS LINE
        }
    }

You can get the root component (JFrame) using the SwingUtilities.getRoot(comp) from the child component and call the pack() method after your new Row is added to your RowList.

This would resize your JPanel. But your RowList will be horizontal. This is where LayoutManager comes into play.

You can know more about different LayoutManagers here.

To fix this problem, in your RowList panel, set your layout to:

setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
always_a_rookie
  • 4,515
  • 1
  • 25
  • 46
-1

Within your refresh method call doLayout() method after revalidate()

Ram Krishna
  • 130
  • 7