使用可滚动的JTextField调整大小问题

时间:2012-02-29 01:06:02

标签: java swing jscrollpane jtextfield scrollable

我有一个包含大量文本字段的表单,其中一些文本字段可能包含很长的字符串。为了使它工作,我使用以下代码使这些文本字段可滚动:

JScrollPane scroll = new JScrollPane(textField);
scroll.setPreferredSize(new Dimension((int)textField.getPreferredSize().getWidth(), (int)textField.getPreferredSize().getHeight() * 2));

然后我使用GridBagLayout将滚动放入我的表单。

我的示例中的第二行是滚动条显示所必需的。但它有缺点。当我调整窗口大小以适应文本字段中的整个文本时,滚动消失,只留下两倍高于其他文本字段,这看起来很荒谬。 如何隐藏卷轴后,如何使这一切工作并显示正常大小的文本字段?

修改

您可以使用以下作为演示代码来重现该问题:

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

public class ScrollTextDemo extends JFrame{

public  ScrollTextDemo(){
    super();
    this.setPreferredSize(new Dimension(500, 300));
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
    textField.setCursor(new Cursor(0));
    textField.setEditable(false);
    JScrollPane scroll = new JScrollPane(textField);
    scroll.setPreferredSize(new Dimension(70, 40) );
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 1;
    gbc.gridy = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weightx = 0.5;
    gbc.insets = new Insets(5, 5, 0, 5);
    panel.add(scroll,gbc);
    //let's add one more text field without scroll bar to compare
    JTextField textField2 = new JTextField("abc");
    gbc = new GridBagConstraints();
    gbc.gridx = 1;
    gbc.gridy = 2;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weightx = 0.5;
    gbc.insets = new Insets(5, 5, 0, 5);
    panel.add(textField2,gbc);
    this.add(panel);
} 

public static void main(String args[]){
    ScrollTextDemo demo = new ScrollTextDemo();
    demo.pack();
    demo.setVisible(true);
}
}

2 个答案:

答案 0 :(得分:4)

为此,在没有好SSCCE的情况下,我认为你没有提供任何填充的约束,用于

当组件的显示区域大于组件的请求大小时使用,以确定是否以及如何调整组件大小。有效值(定义为GridBagConstraints常量)包括NONE(默认值),HORIZONTAL(使组件足够宽以水平填充其显示区域,但不更改其高度),VERTICAL(使组件足够高以垂直填充其显示区域) ,但不要改变它的宽度)和BOTH(使组件完全填满其显示区域)。

所以你必须在GridBagConstraints

中添加这样的东西

constraintsGridBag.fill = GridBagConstraints.HORIZONTAL;

这只允许它不是双向扩展HORIZONTALLY。

**编辑:至于添加的代码**

永远不要为Swing中的任何组件指定setPreferredSize(...)。让您使用布局管理器,注意这一点。删除所有setPreferredSize(...)的东西,在调整大小时让它保持正常大小。

* 编辑2:*

代码告诉你我在说什么:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;

import java.awt.event.*;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

public class GridBagTest extends JFrame
{
    private JPanel topPanel;
    private JPanel bottomPanel;

    public GridBagTest()
    {
        setLayout(new GridBagLayout());

        GridBagConstraints gbc = new GridBagConstraints();      
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        //gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.fill = GridBagConstraints.BOTH;
        gbc.weightx = 1.0;
        gbc.weighty = 0.8;

        // Setting TOP PANEL.
        topPanel  = new JPanel();
        topPanel.setLayout(new GridBagLayout());
        GridBagConstraints constraintsTopPanel = new GridBagConstraints();
        constraintsTopPanel.gridwidth = 2; // Specifies that this component will take two columns.
        constraintsTopPanel.gridheight = 1; // specifies that the component will take one row.
        /*
         *  fill with HORIZONTAL, means the component upon resize, will
         * only expand along the X-Axis.
         */
        constraintsTopPanel.fill = GridBagConstraints.NONE;
        constraintsTopPanel.insets = new Insets(5, 5, 5, 5);
        constraintsTopPanel.ipadx = 2;
        constraintsTopPanel.ipady = 2;
        constraintsTopPanel.weightx = 0.3;
        constraintsTopPanel.weighty = 0.2;

        constraintsTopPanel.gridx = 0;
        constraintsTopPanel.gridy = 0;
        JTextField tfield1 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
        topPanel.add(tfield1, constraintsTopPanel);

        constraintsTopPanel.gridx = 2;
        constraintsTopPanel.gridy = 0;
        final JTextField tfield2 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);              
        topPanel.add(tfield2, constraintsTopPanel);

        constraintsTopPanel.gridx = 4;
        constraintsTopPanel.gridy = 0;
        JTextField tfield3 = new JTextField("kajslkajfkl dsjlafj lksdj akljsd lfkajflkdj lkaj flkdjalk jflkaj lkfdsj salkj flkaj flkja dslkfjal ksjdflka jlfjd aflsdj", 10);
        topPanel.add(tfield3, constraintsTopPanel);

        topPanel.setBackground(Color.WHITE);
        add(topPanel, gbc);

        constraintsTopPanel.gridx = 0;
        constraintsTopPanel.gridy = 2;
        constraintsTopPanel.gridwidth = 6; // Specifies that this component will take two columns.
        constraintsTopPanel.gridheight = 1; // specifies that the component will take one row.

        JButton button = new JButton("REMOVE");
        button.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent ae)
            {
                topPanel.remove(tfield2);
                topPanel.revalidate();
                topPanel.repaint();
            }
        });
        topPanel.add(button, constraintsTopPanel);

        //Setting BOTTOM PANEL.
        bottomPanel = new JPanel();
        bottomPanel.setLayout(new BorderLayout());
        bottomPanel.setBackground(Color.DARK_GRAY);     
        JLabel label3 = new JLabel("I am a new JLABEL for the bottom JPanel", JLabel.CENTER);
        label3.setForeground(Color.WHITE);
        bottomPanel.add(label3, BorderLayout.CENTER);       
        gbc.weighty = 0.2;      
        add(bottomPanel, gbc);

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        pack();
        setVisible(true);
    }

    public static void main(String... args)
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable()
            {
                public void run()
                {
                    new GridBagTest();
                }
            });
    }
}

答案 1 :(得分:0)

我所拥有的最好的东西在代码中看起来很丑陋,但确实完全符合我对textField的要求。以下是从初始问题更改的示例代码。我会感谢任何想法如何让它变得更好:

import javax.swing.*;
import java.awt.*;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

public class ScrollTextDemo extends JFrame{

public  ScrollTextDemo(){
    super();
    this.setPreferredSize(new Dimension(500, 300));
    JPanel panel = new JPanel();
    panel.setLayout(new GridBagLayout());
    JTextField textField = new JTextField("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
    textField.setCursor(new Cursor(0));
    textField.setEditable(false);
    JScrollPane scroll = new JScrollPane(textField, JScrollPane.VERTICAL_SCROLLBAR_NEVER,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
    GridBagConstraints gbc = new GridBagConstraints();
    gbc.gridx = 1;
    gbc.gridy = 1;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weightx = 0.5;
    //gbc.ipady = 20;//gives some room for scroll to appear and don't hide text area under the scroll.
    gbc.insets = new Insets(5, 5, 0, 5);
    panel.add(scroll,gbc);
    //let's add one more text field without scroll bar to compare
    JTextField textField2 = new JTextField("bbbbbbbb");
    gbc = new GridBagConstraints();
    gbc.gridx = 1;
    gbc.gridy = 2;
    gbc.fill = GridBagConstraints.HORIZONTAL;
    gbc.weightx = 0.5;
    gbc.insets = new Insets(5, 5, 0, 5);
    panel.add(textField2,gbc);
    scroll.addComponentListener( new ScrollTextComponentListener(scroll, textField2));
    this.add(panel);
}



public static void main(String args[]){
    ScrollTextDemo demo = new ScrollTextDemo();
    demo.pack();

    demo.setVisible(true);
}
}

class ScrollTextComponentListener implements ComponentListener {
private boolean scrollVisible;
private JScrollPane scroll;
private JComponent compareComponent;

public ScrollTextComponentListener(JScrollPane scroll, JComponent compareComponent) {
    this.scroll = scroll;
    this.compareComponent = compareComponent;
}

private boolean isScrollVisible() {
    return scroll.getHorizontalScrollBar().getModel().getExtent() != scroll.getHorizontalScrollBar().getModel().getMaximum();
}

private void setScrollSize(){
    boolean scrollVisible = isScrollVisible();
    if (scrollVisible){
        scroll.setPreferredSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
        //also had to set both min and max sizes, because only preffered size didn't always work
        scroll.setMinimumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
        scroll.setMaximumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()*2));
    }
    else {
        scroll.setPreferredSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
        scroll.setMinimumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
        scroll.setMaximumSize(new Dimension(compareComponent.getWidth(),compareComponent.getHeight()));
    }
    this.scrollVisible = scrollVisible;
}

@Override
public void componentResized(ComponentEvent e) {
    if (isScrollVisible() != scrollVisible) setScrollSize();
}

@Override
public void componentMoved(ComponentEvent e) {
}

@Override
public void componentShown(ComponentEvent e) {
    setScrollSize();
}

@Override
public void componentHidden(ComponentEvent e) {
}

}