Adding JScrollPane in JTextArea using GridBagLayou

2019-07-13 07:08发布

问题:

I'm having an issue adding JScrollPane in JTextArea using GridBagLayout. Basically the program runs fine when the scrollbar isn't needed but the layout gets messed up and the content gets cut off when it is. The relevent code is as follows

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

public class testGUI extends JFrame
{
    public static String name;
    static JTextField textfield = new JTextField(30);
    static JTextArea  textarea = new JTextArea(30,30);

    public static void main( String[] args)
    {

        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("Checkem");
        frame.setLocation(500,400);
        frame.setSize(800,800);

        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        JScrollPane scrolltxt = new JScrollPane(textarea,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        scrolltxt.setWheelScrollingEnabled(true); 
        scrolltxt.getVerticalScrollBar().isVisible();
        panel.add(scrolltxt, c); 

        JLabel label = new JLabel("Enter the Name of the file:");
        c.gridx = 0;
        c.gridy = 0;
        c.insets = new Insets(2,2,2,2);

        panel.add(label,c);

        c.gridx = 0;
        c.gridy = 1;
        panel.add(textarea,c);      

        JButton button = new JButton("Search");
        c.gridx = 1;
        c.gridy = 1;
        panel.add(button,c);

        c.gridx = 1;
        c.gridy = 0;
        panel.add(textfield,c);


        frame.getContentPane().add(panel, BorderLayout.NORTH);
        frame.pack();
        frame.setVisible(true);

        button.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                Checkem record = new Checkem();
                name = textfield.getText();         
                String [] print = record.run(name);

                for (int i=0;i<print.length;i++)
                {
                    if(print[i] == null || print[i].isEmpty())
                    {
                        continue;
                    }
                    else
                    {
                        textarea.append(print[i] + "\n");
                    }
                }
            }
        });

    }
}

I'm really new to swing and I'm really at a loss where to go from here. Thanks for all your help.

回答1:

  • First please learn Java Naming Conventions, that makes it a bit easier for the other person to understand the Java code.

Now to the actual thingy :-)

  • Why not simply use JTextArea.setLineWrap(true) and JTextArea.setWrapStyleWord(true) instead of defining JScrollBar policy, this will even look nice on the view :-)
  • Moreover, instead of specifying setSize()/setLocation() methods, simply use frameReference.pack() and frame.setLocationByPlatform(true), a very wonderful answer regarding the benefit of the latter is mentioned in this answer, how to best position Swing GUIs
  • Do not make so many static fields in a class, this smells like a bad programming design, and makes your class less extensible.
  • You are extending JFrame to your TestGUI class and then inside it's main() method you creating an instance of the same. Actually again, try to give more weightage to composition over inheritance, since over here, you not actually trying to modify the already defined features of JFrame, instead you just using them as is, so there is no need to extend JFrame in this case atleast :-)
  • Read about Concurrency in Swing

Here is your modified code :

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

public class TestGUI {

    private String name;
    private JTextField textfield = new JTextField(30);
    private JTextArea  textarea = new JTextArea(30,30);

    private void displayGUI() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setTitle("Checkem");        

        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        textarea.setLineWrap(true);
        textarea.setWrapStyleWord(true);
        JScrollPane scrolltxt = new JScrollPane();
        scrolltxt.setViewportView(textarea);
        scrolltxt.setWheelScrollingEnabled(true);

        JLabel label = new JLabel("Enter the Name of the file:");
        c.gridx = 0;
        c.gridy = 0;
        c.insets = new Insets(2,2,2,2);

        panel.add(label,c);

        c.gridx = 0;
        c.gridy = 1;
        panel.add(scrolltxt,c);      

        JButton button = new JButton("Search");
        c.gridx = 1;
        c.gridy = 1;
        panel.add(button,c);

        c.gridx = 1;
        c.gridy = 0;
        panel.add(textfield,c);


        frame.getContentPane().add(panel, BorderLayout.NORTH);      
        //frame.setSize(800,800);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);

        button.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                /*Checkem record = new Checkem();
                name = textfield.getText();         
                String [] print = record.run(name);

                for (int i=0;i<print.length;i++)
                {
                    if(print[i] == null || print[i].isEmpty())
                    {
                        continue;
                    }
                    else
                    {
                        textarea.append(print[i] + "\n");
                    }
                }*/
            }
        });
    }

    public static void main( String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                new TestGUI().displayGUI();
            }
        };
        EventQueue.invokeLater(r);
    }
}


回答2:

You add the JScrollPane, but then you add the JLabel into the same grid position. Then you add the raw JTextArea without the JScrollPane later.

Try this which only adds the JScrollPane that contains your JTextArea. I also moved your GUI creation into a constructor that is called with a SwingUtilities.invokeLater call to ensure it is on the EDT. See Concurrency in Swing for more details on the EDT. This also allows you to not have all your class member variables static, which is not very good practice.

import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class TestGUI extends JFrame {

    String name;
    JTextField textfield = new JTextField(30);
    JTextArea textarea = new JTextArea(30, 30);

    public TestGUI() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        JScrollPane scrolltxt = new JScrollPane(textarea);

        JLabel label = new JLabel("Enter the Name of the file:");
        c.gridx = 0;
        c.gridy = 0;
        c.insets = new Insets(2, 2, 2, 2);

        panel.add(label, c);
        c.gridx = 0;
        c.gridy = 1;
        panel.add(scrolltxt, c);

        JButton button = new JButton("Search");
        c.gridx = 1;
        c.gridy = 1;
        panel.add(button, c);

        c.gridx = 1;
        c.gridy = 0;
        panel.add(textfield, c);

        frame.getContentPane().add(panel, BorderLayout.NORTH);
        frame.pack();
        frame.setVisible(true);

        button.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                Checkem record = new Checkem();
                name = textfield.getText();
                String [] print = record.run(name);

                for (int i=0;i<print.length;i++) {
                    if(print[i] == null || print[i].isEmpty()) {
                        continue;
                    } else {
                        textarea.append(print[i] + "\n");
                    }
                }
            }
        });
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TestGUI();
            }
        });
    }
}