Hot questions for Using JTextField in jscrollpane

Question:

I have JTextFields and JLabels added to my JPanel (from left to right) every time the JButton is pressed. However, every new JTextField and JLabelthat is added becomes smaller and smaller. How do I fix this?

Also I would like to add a JScrollPane to the JPanel but having problems doing so.

     public class MyExample 
{
    // Field members
    static JPanel panel = new JPanel();
    static Integer indexer = 1;
    static List<JLabel> listOfLabels = new ArrayList<JLabel>();
    static List<JTextField> listOfTextFields = new ArrayList<JTextField>();
    static JScrollPane scrollPane = new JScrollPane( panel );

    public static void main(String[] args)
    {       
        // Construct frame
        JFrame frame = new JFrame();
        frame.setLayout(new GridBagLayout());
        frame.setPreferredSize(new Dimension(2000, 2000));
        frame.setTitle("My Example");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.getContentPane().add(scrollPane);

        // Frame constraints
        GridBagConstraints frameConstraints = new GridBagConstraints();

        // Construct button
        JButton addButton = new JButton("Add");
        addButton.addActionListener(new ButtonListener());

        // Add button to frame
        frameConstraints.gridx = 0;
        frameConstraints.gridy = 0;
        frame.add(addButton, frameConstraints);

        // Construct panel
        panel.setPreferredSize(new Dimension(1000, 1000));
        panel.setLayout(new GridBagLayout());
        panel.setBorder(LineBorder.createBlackLineBorder());

        // Add panel to frame
        frameConstraints.gridx = 0;
        frameConstraints.gridy = 1;
        frameConstraints.weighty = 1;
        frame.add(panel, frameConstraints);

        // Pack frame
        frame.pack();

        // Make frame visible
        frame.setVisible(true);
    }

    static class ButtonListener implements ActionListener
    {
        @Override
        public void actionPerformed(ActionEvent arg0) 
        {       
            // Clear panel
            panel.removeAll();

            // Create label and text field
            JTextField jTextField = new JTextField();
            jTextField.setSize(100, 200);
            listOfTextFields.add(jTextField);
            listOfLabels.add(new JLabel("Label " + indexer));

            // Create constraints
            GridBagConstraints textFieldConstraints = new GridBagConstraints();
            GridBagConstraints labelConstraints = new GridBagConstraints();

            // Add labels and text fields
            for(int i = 0; i < indexer; i++)
            {
                // Text field constraints
                textFieldConstraints.gridx = i;
                textFieldConstraints.fill = GridBagConstraints.HORIZONTAL;
                textFieldConstraints.weightx = 0.5;
                textFieldConstraints.insets = new Insets(10, 10, 10, 10);
                textFieldConstraints.gridy = 1;

                // Label constraints
                labelConstraints.gridx = i;
                labelConstraints.gridy = 0;
                labelConstraints.insets = new Insets(10, 10, 10, 10);

                // Add them to panel
                panel.add(listOfLabels.get(i), labelConstraints);
                panel.add(listOfTextFields.get(i), textFieldConstraints);
            }

            // Align components
            GridBagConstraints c = new GridBagConstraints();
            c.gridx = 0;
            c.gridy = indexer;
            c.weighty = 1;
            panel.add(new JLabel(), c);

            // Increment indexer
            indexer++;
            panel.updateUI();
        }
    }
}

Answer:

However, every new JTextField and JLabelthat is added becomes smaller and smaller. How do I fix this?

panel.setPreferredSize(new Dimension(1000, 1000));

Don't set the preferred size. If the size is fixed then as you add more components they need to shrink to fit in the allowed space.

Don't attempt to set the size of any component. Let the layout manager do its job and determine the preferred size of the panel.

When creating a JTextField the code should be something like:

//JTextField jTextField = new JTextField();
JTextField jTextField = new JTextField(10);

This will allow the text field to determine its own preferred size to dispaly about 10 characters.

panel.updateUI();

Don't use updateUI(). That is used internally by Swing when you change the LAF. When you remove/add components you should be using:

panel.revalidate();
panel.repaint();

Question:

I want to reduce the width and height of both the JTextField and JScrollPane in a GridBagLayout, but seems like the width is only reducible to the length of the longest content from the JList, by setting the text field columns. I'm not sure if I need to adjust both or just one of the sizes of the components to match the width.

I've tried setPreferredSize(), setSize(), and setting the column length on the text field but they don't seem to do anything.

    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridx = 0;
    c.gridy = 0;
    fontDialog.add(fontLabel, c);
    c.gridx = 1;
    fontDialog.add(styleLabel,c);
    c.gridx = 2;
    fontDialog.add(sizeLabel, c);
    c.gridx = 0;
    c.gridy = 1;
    fontDialog.add(fontTextField, c);
    c.gridx = 1;
    fontDialog.add(styleTextField, c);
    c.gridx = 2;
    fontDialog.add(sizeTextField, c);
    c.gridx = 0;
    c.gridy = 2;
    fontDialog.add(new JScrollPane(fontList), c);
    c.gridx = 1;
    fontDialog.add(new JScrollPane(styleList), c);
    c.gridx = 2;
    fontDialog.add(new JScrollPane(sizeList), c);
    fontDialog.pack();

Answer:

Components are displayed at their preferred size when added to a cell in the GridBagLayout.

c.fill = GridBagConstraints.HORIZONTAL;

You are using horizontal fill which tells the layout to fill the width of all the components to the largest width in the column, therefore overriding the preferred size.

If you don't want the text fields to increase in width, then get rid of that constraint.

Then when you create the text field you use:

JTextField textField = new JTextField(10);

The number will allow the text field to determine its own preferred size to hold 10 "W" characters.

Question:

I have to admit, maybe the question seems strange how is written, but I'll explain here:

I have a JScrollPane, in which i correctly add a JPanel, let'sa say that for now JScrollPane variable is "JSP" and JPanel is "JP"

In my JP i have an ArrayList of JPanel (let's call it AJP) which i can control visibility from outside the JSP, i can control this visibility by clicking different buttons, every button is "linked" with a number so if i click button1, the first AJP element get visibility set to true, and all the others set to false.

Every of these AJP elements has a different elements inside, so for example, AJP at first position has two JTextFields and 1 JButton, AJP at position 2 has 1 JTextField only.

The fact is that seems that i can't click a JButton or edit a JTextField, like the mouse can't focus them, I'll post here some code

This is the class which contains the JP and it's an extension of JScrollPane

private int x, y, width, height;

private JPanel internalPanel = new JPanel();
private ArrayList<KPanel> kPanels = new ArrayList<KPanel>();

JViewport viewport = new JViewport();

public KScrollPanel(int x, int y, int width, int height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;


    this.internalPanel.setBorder(new LineBorder(Color.black, 1));
    this.internalPanel.setSize(new Dimension(this.width - 10, this.height - 10));
    this.internalPanel.setPreferredSize(new Dimension(this.width - 10, this.height - 10));

    this.setSize(new Dimension(this.internalPanel.getWidth() + 10, this.internalPanel.getHeight() + 10));
    this.setPreferredSize(this.internalPanel.getSize());

    this.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
    this.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

    viewport.add(this.internalPanel);

}

This other is the class which pratically is composed the ArrayList in the class KScrollPanel i just posted, as you can see, the method initialize adds dinamically the elements (KButton and KTextFields are two classes extendind JButton and JTextField)

This class of course is an extension of JPanel

private int x, y, width, height;

KTextField textfield_nodeName, textfield_relationshipName;
KButton button_saveNode, button_saveRelationship;

public KPanel(int x, int y, int width, int height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    initGUI();
}

public KPanel() {

}

public void initGUI() {
    this.setBounds(this.x, this.y, this.width, this.height);
    this.setBorder(new LineBorder(Color.gray, 1));
}

public void initialize(String type) {
    switch(type) {
        case "Node": 
            textfield_nodeName = new KTextField(5, 5, 200, 30);
            this.add(textfield_nodeName);
            button_saveNode = new KButton(5, 35, 200, 30, "Save Node");
            this.add(button_saveNode);
            break;
        case "Relationship": 
            textfield_relationshipName = new KTextField(5, 5, 250, 30);
            this.add(textfield_relationshipName);

            break;
    }
    this.revalidate();
    this.repaint();
}

Answer:

Why are you extending JScrollPane?

Why are you creating a JViewport?

Why are you createing an internal JPanel to add to the viewport?

You should not be attempting to play with the sizes of any of your components. The layout manager will determine the size of each component.

The component you want to add to the scrollpane should be created separately from the scrollpanel. You can then set the Border of this component when you create it.

JViewport viewport = new JViewport();

...

viewport.add(this.internalPanel);

So it looks to me like you create an internal panel and add it to the viewport but you never add the viewport to the scroll pane, so there are no components to display.

So my suggestion is to get rid of the custom JScrollPane class then is no need to extend it because you are not adding any functionality to the class. Just use a JScrollPane the way it was designed to be used:

JPanel internalPanel = new JPanel();
internalPanel.setBorder(...);
internalPanel.add(...);
JScrollPane scrollPane = new JScrollPane( internalPanel );
scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);