【问题标题】:JScrollPane is not added to JTextAreaJScrollPane 未添加到 JTextArea
【发布时间】:2017-03-05 07:15:22
【问题描述】:

我看到了一些类似这个问题的问题,但我无法解决这个问题。我无法在JTextArea 上看到JScrollPane。谁能指出我在哪里做错了?谢谢。

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();
}
}

【问题讨论】:

  • 尝试从您的代码中删除这一行 add(tarea);
  • 我试过那个方法,但是JTextArea 本身就消失了。
  • NEVER 设置 JTextArea 的边界 - 这样做,您会限制它的大小并保证它不会滚动,即使它包含的文本大于持有它的 JScrollPane。相反,设置它的 rows 和 columns 属性。还要强烈避免使用null 布局,因为这会导致 GUI 不灵活,难以更新和增强。
  • @Hovercraft Full Of Eels 你能粘贴你改进后的代码吗?

标签: java swing jscrollpane jtextarea


【解决方案1】:

您的代码有问题:

  • 您可以通过设置边界来限制 JTextArea 的大小。每当您使用 setBounds、setSize 或 setPreferredSize 执行此操作时,您都会使 JTextArea 的大小rigid,因此如果向其中添加大于此大小的文本,它将不会扩展。这样做通常会导致包含 JScrollPane 在需要时显示滚动条,因为 JTextArea 在需要时不会展开。
  • 您正在使用空布局。虽然空布局和setBounds() 对于 Swing 新手来说似乎是创建复杂 GUI 的最简单和最好的方法,但创建的 Swing GUI 越多,使用它们时遇到的困难就越严重。当 GUI 调整大小时,它们不会调整您的组件大小,它们是增强或维护的皇家女巫,放置在滚动窗格中时它们完全失败,在与原始不同的所有平台或屏幕分辨率上查看时它们看起来很糟糕.
  • 您将 JTextArea 添加到两个容器中,即 GUI 和 JScrollPane,这在 Swing GUI 中是不允许的。

改为:

  • 通过设置 JTextArea 的 rows 和 columns 属性来限制 JTextArea 的查看大小,通过将这些属性传递到 JTextArea 的两个 int 构造函数中最容易实现。
  • 使用嵌套的 JPanel,每个 JPanel 都有自己的布局,以实现复杂但灵活且有吸引力的 GUI。
  • 仅将 JTextArea 添加到 JScrollPane 的视口,然后将 JScrollPane 添加到 GUI。

例如,假设您希望在 GUI 中心的 JScrollPane 内有一个 JTextArea,顶部有一个按钮,下面有一个 JTextField 和一个提交按钮,比如说一个典型的聊天窗口类型的应用程序,您可以将整体布局设置为 BorderLayout ,添加一个使用 GridLayout 的 JPanel,顶部带有按钮,一个 BoxLayout 使用带有 JTextField 和提交按钮的 JPanel,底部带有 JTextArea 的 JScrollPane。它可能看起来像这样:

代码可能如下所示:

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());
    }
}


编辑

与其猜测什么可行,什么不可行,让我们进行实验并创建一个包含两个 JTextArea 的 GUI,其中一个包含由 colRowTextArea 变量设置和保存的列和行属性,另一个包含 JTextArea 的首选大小已设置,并将其变量称为 prefSizeTextArea。

我们将创建一个方法setUpTextArea(...),将 JTextArea 放入 JScrollPane 中,将其放入 JPanel 中,并使用一个按钮将 很多 文本添加到 JTextArea 中,然后查看添加文本时 JTextArea 的行为会发生什么。

这是代码,按下按钮,你自己看看哪个滚动:

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());
    }
}

【讨论】:

  • 我对您提到的第一个问题存有疑问。当有“JScrollPane”时,为什么 JTextArea 必须展开?即使文本内容大于 textarea 也可以通过向右滚动来导航?
  • @S.Srihari:这正是问题所在。要使 JScrollPane 工作,它所拥有的组件必须*扩展到大于 JScrollPane 的视口。如果您修复了所持有组件的大小,则不会发生这种情况,并且不会出现滚动条。相信我——这就是 JScrollPane 和 JTextAreas 的工作原理。
  • 对不起,我错了,或者我可能误解了。但这不是预期的输出吗? (imgur.com/a/1lTDx)。当文本不多时,ScrollPane 不可滚动,当文本占用的区域小于JTextArea 占用的区域时,JScrollPane 仍然不可滚动。但是当文本占用的区域大于JTextArea 占用的区域时,则JScrollPane 是可滚动的。这不是预期和期望的输出吗?
【解决方案2】:

当您将JTextArea 组件与JSrcollPane 组件一起使用时,您应该将大小和位置设置为最后一个组件而不是第一个,并且当您将创建的元素添加到JFrame 时,您应该只添加@987654324 @ 组件,因为它被视为JTextArea 组件的容器,请尝试以下代码:

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();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多