我尝试将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);
...
事情是......当panel1
重新调整大小然后再缩小时JTextArea
变为切断。我的意思是它的行不会恢复为5而是保持为1,所以它的所有文本都在一行中,当然,WrapStyleWord
处于非活动状态:S
所以我的问题是如何在重新调整大小的框架上使JTextArea
恢复原始比例?
这是VerticalLayout代码。
...
好吧,根据Guillaume Polet片段,我尝试编写某种垂直面板 list ,但前面提到的问题发生了:(这是代码
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 + "]";
}
}
}
我不确定如何让JTextArea达到原来的宽度?或者可能有更优化的方式?
答案 0 :(得分:2)
您似乎无法发布SSCCE,所以也许您可以从这个开始,可能会更改它,然后编辑您的问题,向我们展示您遇到的问题。
编辑:(根据更新的问题更改了SSCCE)
问题是滚动窗格的ViewPortView没有实现Scrollable。使用专用类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 + "]";
}
}
}
答案 1 :(得分:1)
我不知道为什么不使用JScrollPane
,LineWrap
和WordWrap
在JScrollPane
中正常工作,然后JPanel
会更好使用另一个LayoutManager
将JTextArea
添加到JScrollPane
JPanel
(我完全忽略使用过的VerticalLayout
)将默认LayoutManager
(FlowLayout
)更改为BorderLayout
将JScrollPane(myTextArea)
添加到BorderLayout.CENTER