JScrollPane is not added to JTextArea

痴心易碎 提交于 2020-01-11 08:06:30

问题


I saw a few questions like this question, but I couldn't get this solved. I cannot get a JScrollPane visible on JTextArea. Can anyone please point out where I have done my mistake? Thanks.

package experiement;

import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Experiment extends JFrame{

   public Experiment(){
   JTextArea tarea=new JTextArea();
   tarea.setBounds(100,100,200,200);
   JScrollPane pan= new JScrollPane();
   pan.setPreferredSize(new Dimension(100,100));
   pan=new      JScrollPane(tarea,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);

   add(pan);
   add(tarea);

    setLayout(null);
    setSize(600,600);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
}

public static void main(String[]aegs){
    Experiment e=new Experiment();
}
}

回答1:


Problems with your code:

  • You constrain the size of your JTextArea by setting its bounds. Whenever you do this, either with setBounds, setSize, or setPreferredSize, you make the JTextArea's size rigid and so it won't expand if text is added to it that is larger than this size. Doing this will usually result in the containing JScrollPane from showing scrollbars when needed since the JTextArea won't expand when needed.
  • You're using null layouts. While null layouts and setBounds() might seem to Swing newbies like the easiest and best way to create complex GUI's, the more Swing GUI'S you create the more serious difficulties you will run into when using them. They won't resize your components when the GUI resizes, they are a royal witch to enhance or maintain, they fail completely when placed in scrollpanes, they look gawd-awful when viewed on all platforms or screen resolutions that are different from the original one.
  • You're adding the JTextArea to two containers, the GUI and the JScrollPane, and this is not allowed in Swing GUI's.

Instead:

  • Constrain the viewed size of the JTextArea by setting its rows and columns properties, something easiest to achieve by passing these into the JTextArea's two int constructor.
  • Use nested JPanels, each with its own layout to achieve complex, yet flexible and attractive GUI's.
  • Add your JTextArea to the JScrollPane's viewport only, and then the JScrollPane to the GUI.

For example say you wanted a JTextArea inside of a JScrollPane within the center of your GUI, with buttons on top and a JTextField and a submit button below, say a typical chat window type application, you could make the overall layout a BorderLayout, add a GridLayout-using JPanel with buttons to the top, a BoxLayout using JPanel with the JTextField and submit button to the bottom, and the JScrollPane holding the JTextArea to the center. It could look like this:

and the code could look like this:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import javax.swing.*;

@SuppressWarnings("serial")
public class Experiment2 extends JPanel {
    private static final int ROWS = 20;
    private static final int COLUMNS = 50;
    private static final int GAP = 3;
    // create the JTextArea, setting its rows and columns properties
    private JTextArea tarea = new JTextArea(ROWS, COLUMNS);
    private JTextField textField = new JTextField(COLUMNS);

    public Experiment2() {
        // create the JScrollPane and pass in the JTextArea
        JScrollPane scrollPane = new JScrollPane(tarea);

        // let's create another JPanel to hold some buttons
        JPanel buttonPanel = new JPanel(new GridLayout(1, 0, GAP, 0));
        buttonPanel.add(new JButton("Save"));
        buttonPanel.add(new JButton("Load"));
        buttonPanel.add(new JButton("Whatever"));
        buttonPanel.add(new JButton("Exit"));

        // create JPanel for the bottom with JTextField and a button
        JPanel bottomPanel = new JPanel();
        bottomPanel.setLayout(new BoxLayout(bottomPanel, BoxLayout.LINE_AXIS));
        bottomPanel.add(textField);
        bottomPanel.add(Box.createHorizontalStrut(GAP));
        bottomPanel.add(new JButton("Submit"));

        setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        // use BorderLayout to add all together
        setLayout(new BorderLayout(GAP, GAP));
        add(scrollPane, BorderLayout.CENTER);  // add scroll pane to the center
        add(buttonPanel, BorderLayout.PAGE_START);  // and the button panel to the top
        add(bottomPanel, BorderLayout.PAGE_END);
    }

    private static void createAndShowGui() {
        Experiment2 mainPanel = new Experiment2();

        JFrame frame = new JFrame("Experiment 2");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.getContentPane().add(mainPanel);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}


EDIT

Rather than guess what works and what doesn't, let's experiment and create a GUI that holds two JTextAreas, one where the columns and rows property is set and held by the colRowTextArea variable, and another where the preferred size of the JTextArea is set, and call its variable the prefSizeTextArea.

We'll create a method, setUpTextArea(...) where we place the JTextArea into a JScrollPane, place this into a JPanel, and have a button that adds lots of text into the JTextArea, and see what happens with the behavior of the JTextArea when text is added.

Here's the code and push the buttons and see for yourself which one scrolls:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import javax.swing.*;

@SuppressWarnings("serial")
public class TwoTextAreas extends JPanel {
    // our nonsense String
    public static final String LoremIpsum = "Lorem ipsum dolor sit amet, "
            + "consectetur adipiscing elit, sed do eiusmod tempor incididunt "
            + "ut labore et dolore magna aliqua. Ut enim ad minim veniam, "
            + "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
            + "commodo consequat. Duis aute irure dolor in reprehenderit in "
            + "voluptate velit esse cillum dolore eu fugiat nulla pariatur. "
            + "Excepteur sint occaecat cupidatat non proident, sunt in culpa "
            + "qui officia deserunt mollit anim id est laborum.";
    private static final int ROWS = 30;
    private static final int COLS = 40;
    private static final Dimension TA_PREF_SIZE = new Dimension(440, 480);
    private JTextArea colRowTextArea = new JTextArea(ROWS, COLS);
    private JTextArea prefSizeTextArea = new JTextArea();

    public TwoTextAreas() {
        setLayout(new GridLayout(1, 0));
        prefSizeTextArea.setPreferredSize(TA_PREF_SIZE);

        add(setUpTextArea(colRowTextArea, "Set Columns & Rows"));
        add(setUpTextArea(prefSizeTextArea, "Set Preferred Size"));

    }

    private JPanel setUpTextArea(JTextArea textArea, String title) {
        // allow word wrapping
        textArea.setLineWrap(true);
        textArea.setWrapStyleWord(true);

        JScrollPane scrollPane = new JScrollPane(textArea);

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(new JButton(new AppendTextAction(textArea)));

        JPanel holderPanel = new JPanel(new BorderLayout());
        holderPanel.setBorder(BorderFactory.createTitledBorder(title));
        holderPanel.add(scrollPane);
        holderPanel.add(buttonPanel, BorderLayout.PAGE_END);
        return holderPanel;
    }

    private class AppendTextAction extends AbstractAction {
        private JTextArea textArea;
        private StringBuilder sb = new StringBuilder();

        public AppendTextAction(JTextArea textArea) {
            super("Append Text to TextArea");
            this.textArea = textArea;

            // create nonsense String
            for (int i = 0; i < 100; i++) {
                sb.append(LoremIpsum);
                sb.append("\n");
            }
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            textArea.append(sb.toString());
        }
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("Two TextAreas");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new TwoTextAreas());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}



回答2:


When you use JTextArea component with JSrcollPane component you should set size and position to the last component and not to the first one, and when you add the created elements to the JFrame you should only add JScrollPane component because it is considered as container to the JTextArea component, try this code:

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;

public class Main extends JFrame
{
    JTextArea tarea;
    JScrollPane pan;
    public Main()
    {
        tarea = new JTextArea();
        pan = new JScrollPane(tarea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
                JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
        pan.setBounds(100, 100, 200, 200);

        add(pan);

        setLayout(null);
        setSize(600, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }

    public static void main(String[] aegs)
    {
        Main f = new Main();
    }
}


来源:https://stackoverflow.com/questions/40202689/jscrollpane-is-not-added-to-jtextarea

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!