3

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.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
user2703771
  • 51
  • 1
  • 4
  • Why not simply use `tArea.setLineWrap(true) and tArea.setWrapStyleWord(true)` instead of defining `ScrollBar` policy, this will even look nice on the view :-) And please learn Java Naming Conventions and stick to them, it becomes a bit hard when someone uses non-conventional terms inside the Java code to understand the code, at the first glance :( – nIcE cOw Aug 26 '13 at 16:34
  • 1
    Moreover, instead of adding the `JTextArea` to the `JPanel` add the `scrolltxt` to the same, since `JTextArea` already is placed inside the `JScrollPane` :-) – nIcE cOw Aug 26 '13 at 16:42

2 Answers2

5
  • 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);
    }
}
Community
  • 1
  • 1
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
3

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();
            }
        });
    }
}
nIcE cOw
  • 24,468
  • 7
  • 50
  • 143
jmclellan
  • 550
  • 3
  • 12
  • +1 for `DISPOSE_ON_CLOSE` and other valuable inputs :-), though this vote will come in 7 hours, since, my limit is gone for the day :( – nIcE cOw Aug 26 '13 at 17:07
  • Thank you for your efforts. Unfortunately the scroll bar still didn't work but I really appreciate the clear up on some of my bad code. I just used JTextArea.setLineWrap(true) and JTextArea.setWrapStyleWord(true) like suggested by nIcE cOw and it worked like a charm. – user2703771 Aug 27 '13 at 11:58