Проблема с размером прокручиваемого JTextField - PullRequest
4 голосов
/ 29 февраля 2012

У меня есть форма с большим количеством текстовых полей, и некоторые из этих текстовых полей могут содержать очень длинные строки. Чтобы это работало, я сделал эти текстовые поля прокручиваемыми с помощью этого кода:

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

Затем я добавляю прокрутку в форму, используя GridBagLayout.

Вторая строка в моем примере требуется для отображения скроллера. Но у этого есть обратная сторона. Когда я изменяю размер окна, чтобы поместить весь текст в текстовое поле, прокрутка исчезает, оставляя меня всего в два раза выше, чем у другого текстового поля, что выглядит нелепо. Как я могу заставить все это работать и показывать мне нормальный размер текстового поля после того, как скроллер скрыт?

EDIT

Для демонстрации проблемы вы можете использовать следующее в качестве демонстрационного кода:

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 ]

4 голосов
/ 29 февраля 2012

Для этого, в отсутствие хорошего SSCCE , я думаю, что вы не предоставили никаких ограничений на заполнение, которое используется для

Используется, когда область отображения компонента больше, чем запрошенный размер компонента, чтобы определить, нужно ли и как изменить размер компонента. Допустимые значения (определяемые как константы GridBagConstraints) включают NONE (по умолчанию), HORIZONTAL (сделать компонент достаточно широким, чтобы заполнить его область отображения по горизонтали, но не изменяйте его высоту), VERTICAL (сделайте компонент достаточно высоким, чтобы заполнить его область отображения по вертикали , но не меняйте его ширину) и ОБА (чтобы компонент полностью заполнил свою область отображения).

Итак, вы должны добавить что-то подобное в ваши GridBagConstraints

constraintsGridBag.fill = GridBagConstraints.HORIZONTAL;

Это позволит только расширяться ГОРИЗОНТАЛЬНО, но не в обе стороны.

** РЕДАКТИРОВАТЬ: Что касается добавленного кода **

Никогда не указывайте setPreferredSize (...) для любого компонента в Swing. Пусть менеджер раскладок, который вы используете, позаботится об этом. Удалите все 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();
                }
            });
    }
}
0 голосов
/ 29 февраля 2012

Что ж, лучшее, что у меня есть, это уродливый код, но он делает именно то, что мне нужно для 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) {
}

}

...