Java resizing individual components of JPanel

2019-09-05 02:31发布

问题:

I have a JPanel with Box.createVerticalBox() layout containing five JPanels. (1) Labels, (2) a table (3) a JTextField (4) a JTextArea (5) buttons.On resize:

labels should stick to top left corner and keep the same size,
JTextField should stick to left size between (2) and (4) and expand to full width of the frame
Buttons should stick to bottom right corner and keep the same size,
JTable and JTextArea should expand to full width of the frame and equally divide remaining space

I've tried several layouts, but couldn't make resizing work. To run this program two classes are required EditPanel.java :

import java.awt.BorderLayout;
import java.awt.FlowLayout;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextField;

public class EditPanel extends JPanel {
    private JPanel p1Labels;
    private JPanel p2Table;
    private JPanel p3ecnTitle;
    private JPanel p5Buttons;    
    private JTextField fieldK;
    private JTextField fieldS;
    private JScrollPane myScrollBar;
    private Box theBox;

    public EditPanel() {
        init();
    }

    public void init() {  // Creating a vertical Box layout with five sections, placing jpanels there

        //First panel with buttons

        p1Labels = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 2));
        fieldK = new JTextField("Animal");
        fieldS = new JTextField("Fox");        
        p1Labels.add(new JLabel("Kindom: "));
        p1Labels.add(fieldK);
        p1Labels.add(new JLabel("Species: "));
        p1Labels.add(fieldS);

        //Second panel with a table

        p2Table = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 2));
        String[] columnNames = {"First", "Second", "Third", "Fourth"};
        Object[][] data = {{"11", "12", "13", "Forteen"},{"21", "22", "23", "Twenty four"}}; 
        JTable table = new JTable(data, columnNames);
        JScrollPane scrollPane1 = new JScrollPane(new JTable(data, columnNames));
        table.setFillsViewportHeight(true);
        p2Table.add(scrollPane1, BorderLayout.CENTER);

        //Third panel with a JTextField

        p3ecnTitle = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 2)); 
        p3ecnTitle.add(new JLabel("Title: "));
        p3ecnTitle.add(new JTextField("", 14));

        //Forth panel with JTextArea
        //p4TextArea = new JPanel(new FlowLayout(FlowLayout.LEFT, 2, 2));//tried this too
        JTextArea ecnArea = new JTextArea(10, 20);        
        ecnArea.setText("");
        ecnArea.setName("Note");
        ecnArea.setLineWrap(true);
        ecnArea.setWrapStyleWord(true);
        myScrollBar = new JScrollPane(ecnArea,
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);  

        //Fifth container with buttons

        p5Buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT, 2, 2));
        p5Buttons.add(new JButton("SAVE"));
        p5Buttons.add(new JButton("DELETE"));
        p5Buttons.add(new JButton("CANCEL")); 

        //Placing everything in a container
        theBox = Box.createVerticalBox();
        theBox.add(p1Labels);
        theBox.add(p2Table);
        theBox.add(p3ecnTitle);
        //theBox.add(p4TextArea);
        theBox.add(myScrollBar);
        theBox.add(Box.createVerticalGlue());
        theBox.add(p5Buttons);
        this.add(theBox);
    }
}

And the main.java

import javax.swing.JFrame;
public class Main {
    public static void main(String[] args) {
        JFrame myFrame;
        myPanel EditECNDialog;
        myFrame = new JFrame();     
        EditECNDialog = new myPanel();
        myFrame.setTitle("Notes");
        myFrame.add(EditECNDialog);
        myFrame.pack();
        myFrame.setLocationRelativeTo(null);
        myFrame.setVisible(true);
    }
}

Which Layout handles resizing the best? Can boxlayout handle resizing?

回答1:

GridBagLayout is the best layout manager for your app. See https://docs.oracle.com/javase/tutorial/uiswing/layout/gridbag.html



回答2:

You can use a GridBagLayout as Wabbi has already suggested. However is does have the limitation I noted in the comments.

However, if you truly want the textarea and table to always be the same size then you can use the Relative Layout. This layout will first allocate space to components with a fixed size. Then any space remaining is allocated to the components with a relative constraint.

So the basic code would be:

RelativeLayout rl = new RelativeLayout(RelativeLayout.Y_AXIS);
rl.setFill( true );
JPanel panel = new JPanel( rl );
panel.add(labelPanel);
panel.add(tableScrollPane, new Float(1));
panel.add(textField);
panel.add(textAreaScrollPane, new Float(1)); 
panel.add(buttonsPanel);

Now the table and text area will grow/shrink equally as the frame is resized.

Can boxlayout handle resizing?

Yes it can handle this type of resizing. Box layout respects the maximum size of a component. So if you override the getMaximumSize() method of your panels to return getPreferredSize(), then the panels will not grow in height.

So extra space will be given to the scrollpanes of the text area and table. Again, same concern. Each component will originally be allocated space based on its preferred size.



回答3:

You should use one variable for gridbagconstraints. This way you can do c.gridy++; c.gridx=0; and c.gridx++;
It will be easier to insert new components later. Explicit d.gridy=4; makes inserting new components difficult.