简体   繁体   English

JTextArea不会调整大小

[英]JTextArea doesn't resize

I tried to set JTextArea to JPanel as 我试图将JTextArea设置为JPanel

JPanel panel=new JPanel(new BorderLayout());
JTextArea ta=new JTextArea();
ta.setColumns(20);
ta.setEditable(false);
ta.setLineWrap(true);
ta.setRows(5);
ta.setWrapStyleWord(true);

panel.add(ta,BorderLayout.CENTER);

JPanel panel1=new JPanel();
panel1.setLayout(new VerticalLayout(5,VerticalLayout.BOTH));
panel1.add(panel);

JFrame frame=new JFrame();
frame.getContentPane().add(panel1);
    ...

The thing is... when the panel1 is re-sized wider and then back narrower the JTextArea becomes cut off . 问题是...当将panel1的大小重新调整为更宽,然后再向后缩小时, JTextArea就会被切断 I mean its rows do not restore to 5 but hold as 1 and so all its text is in one line , of course, the WrapStyleWord is inactive :S 我的意思是它的行不会恢复为5而是保持为1,因此其所有文本都在一行中,当然WrapStyleWord是不活动的:S

So my question is how to make the JTextArea restore to its original scale on frame re-sized? 所以我的问题是如何在重新调整框架大小时使JTextArea恢复到其原始比例?

Here is the VerticalLayout code. 这是VerticalLayout代码。

... ...

Well, based on Guillaume Polet snippet, I tried to write some kind of vertical panels list but the previously mentioned problem takes place :( Here is the code 好吧,基于Guillaume Polet片段,我尝试编写某种垂直面板列表,但是发生了前面提到的问题:(这是代码

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.util.Hashtable;

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

public class TestTextArea {

    private void initUI() {
        JFrame frame = new JFrame("test");


        JPanel listPanel = new JPanel();
        listPanel.setLayout(new VerticalLayout(5, VerticalLayout.BOTH));


        JPanel mainPanel=new JPanel(new GridLayout());
        JScrollPane sp=new JScrollPane();
        sp.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        sp.setViewportView(listPanel);

        mainPanel.add(sp);

        listPanel.add(new MyPanel());
        listPanel.add(new MyPanel());
        listPanel.add(new MyPanel());
        listPanel.add(new MyPanel());
        listPanel.add(new MyPanel());

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestTextArea().initUI();
            }
        });
    }

    class MyPanel extends JPanel
    {
        public MyPanel(){

        this.setLayout(new BorderLayout());

        JTextArea ta = new JTextArea();
        ta.setText("Hello world Hello world Hello world Hello world " + "Hello world Hello world Hello world Hello world "
                + "Hello world Hello world Hello world Hello world " + "Hello world Hello world Hello world Hello world ");
        ta.setColumns(20);
        ta.setEditable(false);
        ta.setLineWrap(true);
        ta.setRows(5);
        ta.setWrapStyleWord(true);

        this.add(ta, BorderLayout.CENTER);


        }

    }

    public static class VerticalLayout implements LayoutManager {

        /**
         * The horizontal alignment constant that designates centering. Also used to designate center anchoring.
         */
        public final static int CENTER = 0;
        /**
         * The horizontal alignment constant that designates right justification.
         */
        public final static int RIGHT = 1;
        /**
         * The horizontal alignment constant that designates left justification.
         */
        public final static int LEFT = 2;
        /**
         * The horizontal alignment constant that designates stretching the component horizontally.
         */
        public final static int BOTH = 3;

        /**
         * The anchoring constant that designates anchoring to the top of the display area
         */
        public final static int TOP = 1;
        /**
         * The anchoring constant that designates anchoring to the bottom of the display area
         */
        public final static int BOTTOM = 2;
        private int vgap; // the vertical vgap between components...defaults to 5
        private int alignment; // LEFT, RIGHT, CENTER or BOTH...how the components are justified
        private int anchor; // TOP, BOTTOM or CENTER ...where are the components positioned in an overlarge space
        private Hashtable comps;

        // Constructors
        /**
         * Constructs an instance of VerticalLayout with a vertical vgap of 5 pixels, horizontal centering and anchored to the top of the
         * display area.
         */
        public VerticalLayout() {
            this(5, CENTER, TOP);
        }

        /**
         * Constructs a VerticalLayout instance with horizontal centering, anchored to the top with the specified vgap
         *
         * @param vgap
         *            An int value indicating the vertical seperation of the components
         */
        public VerticalLayout(int vgap) {
            this(vgap, CENTER, TOP);
        }

        /**
         * Constructs a VerticalLayout instance anchored to the top with the specified vgap and horizontal alignment
         *
         * @param vgap
         *            An int value indicating the vertical seperation of the components
         * @param alignment
         *            An int value which is one of <code>RIGHT, LEFT, CENTER, BOTH</code> for the horizontal alignment.
         */
        public VerticalLayout(int vgap, int alignment) {
            this(vgap, alignment, TOP);
        }

        /**
         * Constructs a VerticalLayout instance with the specified vgap, horizontal alignment and anchoring
         *
         * @param vgap
         *            An int value indicating the vertical seperation of the components
         * @param alignment
         *            An int value which is one of <code>RIGHT, LEFT, CENTER, BOTH</code> for the horizontal alignment.
         * @param anchor
         *            An int value which is one of <code>TOP, BOTTOM, CENTER</code> indicating where the components are to appear if the
         *            display area exceeds the minimum necessary.
         */
        public VerticalLayout(int vgap, int alignment, int anchor) {
            this.vgap = vgap;
            this.alignment = alignment;
            this.anchor = anchor;
        }

        // ----------------------------------------------------------------------------
        private Dimension layoutSize(Container parent, boolean minimum) {
            Dimension dim = new Dimension(0, 0);
            Dimension d;
            synchronized (parent.getTreeLock()) {
                int n = parent.getComponentCount();
                for (int i = 0; i < n; i++) {
                    Component c = parent.getComponent(i);
                    if (c.isVisible()) {
                        d = minimum ? c.getMinimumSize() : c.getPreferredSize();
                        dim.width = Math.max(dim.width, d.width);
                        dim.height += d.height;
                        if (i > 0) {
                            dim.height += vgap;
                        }
                    }
                }
            }
            Insets insets = parent.getInsets();
            dim.width += insets.left + insets.right;
            dim.height += insets.top + insets.bottom + vgap + vgap;
            return dim;
        }

        // -----------------------------------------------------------------------------
        /**
         * Lays out the container.
         */
        @Override
        public void layoutContainer(Container parent) {
            Insets insets = parent.getInsets();
            synchronized (parent.getTreeLock()) {
                int n = parent.getComponentCount();
                Dimension pd = parent.getSize();
                int y = 0;
                // work out the total size
                for (int i = 0; i < n; i++) {
                    Component c = parent.getComponent(i);
                    Dimension d = c.getPreferredSize();
                    y += d.height + vgap;
                }
                y -= vgap; // otherwise there's a vgap too many
                // Work out the anchor paint
                if (anchor == TOP) {
                    y = insets.top;
                } else if (anchor == CENTER) {
                    y = (pd.height - y) / 2;
                } else {
                    y = pd.height - y - insets.bottom;
                }
                // do layout
                for (int i = 0; i < n; i++) {
                    Component c = parent.getComponent(i);
                    Dimension d = c.getPreferredSize();
                    int x = insets.left;
                    int wid = d.width;
                    if (alignment == CENTER) {
                        x = (pd.width - d.width) / 2;
                    } else if (alignment == RIGHT) {
                        x = pd.width - d.width - insets.right;
                    } else if (alignment == BOTH) {
                        wid = pd.width - insets.left - insets.right;
                    }
                    c.setBounds(x, y, wid, d.height);
                    y += d.height + vgap;
                }
            }
        }

        // -----------------------------------------------------------------------------
        @Override
        public Dimension minimumLayoutSize(Container parent) {
            return layoutSize(parent, false);
        }

        // -----------------------------------------------------------------------------
        @Override
        public Dimension preferredLayoutSize(Container parent) {
            return layoutSize(parent, false);
        }

        // ----------------------------------------------------------------------------
        /**
         * Not used by this class
         */
        @Override
        public void addLayoutComponent(String name, Component comp) {
        }

        // -----------------------------------------------------------------------------
        /**
         * Not used by this class
         */
        @Override
        public void removeLayoutComponent(Component comp) {
        }

        // -----------------------------------------------------------------------------
        @Override
        public String toString() {
            return getClass().getName() + "[vgap=" + vgap + " align=" + alignment + " anchor=" + anchor + "]";
        }
    }

}

I am not pretty sure how to make JTextArea come to its original width? 我不太确定如何使JTextArea达到其原始宽度? Or maybe there is some more optimal way? 还是有一些更优化的方法?

It seems like you are having trouble posting an SSCCE , so maybe you can get started from this one, possibly change it, and then edit your question showing us the problem you are having. 似乎您在发布SSCCE时遇到了麻烦 ,因此也许您可以从此开始,可以进行更改,然后编辑您的问题,向我们显示您遇到的问题。

EDIT: (Changed SSCCE according to updated question) 编辑:(根据更新的问题更改了SSCCE)

The problem is that the ViewPortView of the scrollpane does not implements Scrollable. 问题是滚动窗格的ViewPortView不实现Scrollable。 Try the code below with the dedicated class ScrollablePanel which is added as the ViewPortView. 尝试使用下面的代码使用专用类ScrollablePanel,该类已作为ViewPortView添加。

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.LayoutManager;
import java.awt.Rectangle;
import java.util.Hashtable;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

public class TestTextArea {

    private void initUI() {
        JFrame frame = new JFrame("test");

        class ScrollablePanel extends JPanel implements Scrollable {

            /**
             * Returns the preferred size of the viewport for a view component. This is implemented to do the default behavior of returning
             * the preferred size of the component.
             * 
             * @return the <code>preferredSize</code> of a <code>JViewport</code> whose view is this <code>Scrollable</code>
             */
            @Override
            public Dimension getPreferredScrollableViewportSize() {
                return getPreferredSize();
            }

            /**
             * Components that display logical rows or columns should compute the scroll increment that will completely expose one new row
             * or column, depending on the value of orientation. Ideally, components should handle a partially exposed row or column by
             * returning the distance required to completely expose the item.
             * <p>
             * The default implementation of this is to simply return 10% of the visible area. Subclasses are likely to be able to provide a
             * much more reasonable value.
             * 
             * @param visibleRect
             *            the view area visible within the viewport
             * @param orientation
             *            either <code>SwingConstants.VERTICAL</code> or <code>SwingConstants.HORIZONTAL</code>
             * @param direction
             *            less than zero to scroll up/left, greater than zero for down/right
             * @return the "unit" increment for scrolling in the specified direction
             * @exception IllegalArgumentException
             *                for an invalid orientation
             * @see JScrollBar#setUnitIncrement
             */
            @Override
            public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) {
                switch (orientation) {
                case SwingConstants.VERTICAL:
                    return visibleRect.height / 10;
                case SwingConstants.HORIZONTAL:
                    return visibleRect.width / 10;
                default:
                    throw new IllegalArgumentException("Invalid orientation: " + orientation);
                }
            }

            /**
             * Components that display logical rows or columns should compute the scroll increment that will completely expose one block of
             * rows or columns, depending on the value of orientation.
             * <p>
             * The default implementation of this is to simply return the visible area. Subclasses will likely be able to provide a much
             * more reasonable value.
             * 
             * @param visibleRect
             *            the view area visible within the viewport
             * @param orientation
             *            either <code>SwingConstants.VERTICAL</code> or <code>SwingConstants.HORIZONTAL</code>
             * @param direction
             *            less than zero to scroll up/left, greater than zero for down/right
             * @return the "block" increment for scrolling in the specified direction
             * @exception IllegalArgumentException
             *                for an invalid orientation
             * @see JScrollBar#setBlockIncrement
             */
            @Override
            public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) {
                switch (orientation) {
                case SwingConstants.VERTICAL:
                    return visibleRect.height;
                case SwingConstants.HORIZONTAL:
                    return visibleRect.width;
                default:
                    throw new IllegalArgumentException("Invalid orientation: " + orientation);
                }
            }

            /**
             * Returns true if a viewport should always force the width of this <code>Scrollable</code> to match the width of the viewport.
             * For example a normal text view that supported line wrapping would return true here, since it would be undesirable for wrapped
             * lines to disappear beyond the right edge of the viewport. Note that returning true for a <code>Scrollable</code> whose
             * ancestor is a <code>JScrollPane</code> effectively disables horizontal scrolling.
             * <p>
             * Scrolling containers, like <code>JViewport</code>, will use this method each time they are validated.
             * 
             * @return true if a viewport should force the <code>Scrollable</code>s width to match its own
             */
            @Override
            public boolean getScrollableTracksViewportWidth() {
                return true;
            }

            /**
             * Returns true if a viewport should always force the height of this <code>Scrollable</code> to match the height of the
             * viewport. For example a columnar text view that flowed text in left to right columns could effectively disable vertical
             * scrolling by returning true here.
             * <p>
             * Scrolling containers, like <code>JViewport</code>, will use this method each time they are validated.
             * 
             * @return true if a viewport should force the Scrollables height to match its own
             */
            @Override
            public boolean getScrollableTracksViewportHeight() {
                return false;
            }

        }

        JPanel listPanel = new ScrollablePanel();
        listPanel.setLayout(new VerticalLayout(5, VerticalLayout.BOTH));

        JPanel mainPanel = new JPanel(new GridLayout());
        JScrollPane sp = new JScrollPane();
        sp.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        sp.setViewportView(listPanel);

        mainPanel.add(sp);

        listPanel.add(new MyPanel());
        listPanel.add(new MyPanel());
        listPanel.add(new MyPanel());
        listPanel.add(new MyPanel());
        listPanel.add(new MyPanel());

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(mainPanel);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TestTextArea().initUI();
            }
        });
    }

    class MyPanel extends JPanel {
        public MyPanel() {

            this.setLayout(new BorderLayout());

            JTextArea ta = new JTextArea();
            ta.setText("Hello world Hello world Hello world Hello world " + "Hello world Hello world Hello world Hello world "
                    + "Hello world Hello world Hello world Hello world " + "Hello world Hello world Hello world Hello world ");
            ta.setColumns(20);
            ta.setEditable(false);
            ta.setLineWrap(true);
            ta.setRows(5);
            ta.setWrapStyleWord(true);

            this.add(ta, BorderLayout.CENTER);

        }

    }

    public static class VerticalLayout implements LayoutManager {

        /**
         * The horizontal alignment constant that designates centering. Also used to designate center anchoring.
         */
        public final static int CENTER = 0;
        /**
         * The horizontal alignment constant that designates right justification.
         */
        public final static int RIGHT = 1;
        /**
         * The horizontal alignment constant that designates left justification.
         */
        public final static int LEFT = 2;
        /**
         * The horizontal alignment constant that designates stretching the component horizontally.
         */
        public final static int BOTH = 3;

        /**
         * The anchoring constant that designates anchoring to the top of the display area
         */
        public final static int TOP = 1;
        /**
         * The anchoring constant that designates anchoring to the bottom of the display area
         */
        public final static int BOTTOM = 2;
        private int vgap; // the vertical vgap between components...defaults to 5
        private int alignment; // LEFT, RIGHT, CENTER or BOTH...how the components are justified
        private int anchor; // TOP, BOTTOM or CENTER ...where are the components positioned in an overlarge space
        private Hashtable comps;

        // Constructors
        /**
         * Constructs an instance of VerticalLayout with a vertical vgap of 5 pixels, horizontal centering and anchored to the top of the
         * display area.
         */
        public VerticalLayout() {
            this(5, CENTER, TOP);
        }

        /**
         * Constructs a VerticalLayout instance with horizontal centering, anchored to the top with the specified vgap
         * 
         * @param vgap
         *            An int value indicating the vertical seperation of the components
         */
        public VerticalLayout(int vgap) {
            this(vgap, CENTER, TOP);
        }

        /**
         * Constructs a VerticalLayout instance anchored to the top with the specified vgap and horizontal alignment
         * 
         * @param vgap
         *            An int value indicating the vertical seperation of the components
         * @param alignment
         *            An int value which is one of <code>RIGHT, LEFT, CENTER, BOTH</code> for the horizontal alignment.
         */
        public VerticalLayout(int vgap, int alignment) {
            this(vgap, alignment, TOP);
        }

        /**
         * Constructs a VerticalLayout instance with the specified vgap, horizontal alignment and anchoring
         * 
         * @param vgap
         *            An int value indicating the vertical seperation of the components
         * @param alignment
         *            An int value which is one of <code>RIGHT, LEFT, CENTER, BOTH</code> for the horizontal alignment.
         * @param anchor
         *            An int value which is one of <code>TOP, BOTTOM, CENTER</code> indicating where the components are to appear if the
         *            display area exceeds the minimum necessary.
         */
        public VerticalLayout(int vgap, int alignment, int anchor) {
            this.vgap = vgap;
            this.alignment = alignment;
            this.anchor = anchor;
        }

        // ----------------------------------------------------------------------------
        private Dimension layoutSize(Container parent, boolean minimum) {
            Dimension dim = new Dimension(0, 0);
            Dimension d;
            synchronized (parent.getTreeLock()) {
                int n = parent.getComponentCount();
                for (int i = 0; i < n; i++) {
                    Component c = parent.getComponent(i);
                    if (c.isVisible()) {
                        d = minimum ? c.getMinimumSize() : c.getPreferredSize();
                        dim.width = Math.max(dim.width, d.width);
                        dim.height += d.height;
                        if (i > 0) {
                            dim.height += vgap;
                        }
                    }
                }
            }
            Insets insets = parent.getInsets();
            dim.width += insets.left + insets.right;
            dim.height += insets.top + insets.bottom + vgap + vgap;
            return dim;
        }

        // -----------------------------------------------------------------------------
        /**
         * Lays out the container.
         */
        @Override
        public void layoutContainer(Container parent) {
            Insets insets = parent.getInsets();
            synchronized (parent.getTreeLock()) {
                int n = parent.getComponentCount();
                Dimension pd = parent.getSize();
                int y = 0;
                // work out the total size
                for (int i = 0; i < n; i++) {
                    Component c = parent.getComponent(i);
                    Dimension d = c.getPreferredSize();
                    y += d.height + vgap;
                }
                y -= vgap; // otherwise there's a vgap too many
                // Work out the anchor paint
                if (anchor == TOP) {
                    y = insets.top;
                } else if (anchor == CENTER) {
                    y = (pd.height - y) / 2;
                } else {
                    y = pd.height - y - insets.bottom;
                }
                // do layout
                for (int i = 0; i < n; i++) {
                    Component c = parent.getComponent(i);
                    Dimension d = c.getPreferredSize();
                    int x = insets.left;
                    int wid = d.width;
                    if (alignment == CENTER) {
                        x = (pd.width - d.width) / 2;
                    } else if (alignment == RIGHT) {
                        x = pd.width - d.width - insets.right;
                    } else if (alignment == BOTH) {
                        wid = pd.width - insets.left - insets.right;
                    }
                    c.setBounds(x, y, wid, d.height);
                    y += d.height + vgap;
                }
            }
        }

        // -----------------------------------------------------------------------------
        @Override
        public Dimension minimumLayoutSize(Container parent) {
            return layoutSize(parent, false);
        }

        // -----------------------------------------------------------------------------
        @Override
        public Dimension preferredLayoutSize(Container parent) {
            return layoutSize(parent, false);
        }

        // ----------------------------------------------------------------------------
        /**
         * Not used by this class
         */
        @Override
        public void addLayoutComponent(String name, Component comp) {
        }

        // -----------------------------------------------------------------------------
        /**
         * Not used by this class
         */
        @Override
        public void removeLayoutComponent(Component comp) {
        }

        // -----------------------------------------------------------------------------
        @Override
        public String toString() {
            return getClass().getName() + "[vgap=" + vgap + " align=" + alignment + " anchor=" + anchor + "]";
        }
    }

}

I don't know any reason why not use JScrollPane , LineWrap and WordWrap works correctly in the JScrollPane , then for JPanel will be better to use another LayoutManager 我不知道为什么不使用JScrollPaneLineWrapWordWrapJScrollPane正常工作的任何原因,那么对于JPanel最好使用另一个LayoutManager

  • put JTextArea to the JScrollPane JTextArea放入JScrollPane

  • JPanel required (I'm quite to ignore used VerticalLayout ) to change default LayoutManager ( FlowLayout ) to the BorderLayout 需要使用JPanel (我很想忽略使用的VerticalLayout )将默认LayoutManagerFlowLayout )更改为BorderLayout

  • put JScrollPane(myTextArea) to the BorderLayout.CENTER JScrollPane(myTextArea)放入BorderLayout.CENTER

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM