Swing - как смешивать JTextField и JTextAreas и иметь одинаковый внешний вид?

Я использую miglayout для создания формы, в которой есть JTextFields (короткие ответы на ввод), а также JTextAreas (более длинные ответы). Проблема двоякая.

  1. Граница, расположенная вокруг области прокрутки, не соответствует границе текстового поля.
  2. Ширина и расположение текстовой области/текстового поля различаются, из-за чего они не выстраиваются правильно.

http://grab.by/3O0V

После перехода справа/слева направо/заполнения: http://grab.by/3RMk видно, что границы совпадают , но что есть еще пробелы. Я попытался установить novisualpadding, но это не помогло.

Исходный код:

package test2;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import net.miginfocom.swing.MigLayout;

public class Test extends JPanel {

private static final int NUM_CHARACTERS_WIDTH = 20;
private static final int NUM_ROWS = 5;
public Test() {

    setLayout(new MigLayout(
            "wrap 2",
            // Align text labels on the so their right edge meets left edge of the text fields
            "[right][left]"
            ));

    add(new JLabel("Text field:"));
    add(new JTextField(NUM_CHARACTERS_WIDTH));

    add(new JLabel("No scrollpane text area:"));
    add(new JTextArea(NUM_ROWS, NUM_CHARACTERS_WIDTH));

    add(new JLabel("Scrollpane text area:"));
    add(new JScrollPane(new JTextArea(NUM_ROWS, NUM_CHARACTERS_WIDTH)));

    add(new JLabel("Text field:"));
    add(new JTextField(NUM_CHARACTERS_WIDTH));

}


public static void main(String[] args) {
    JFrame frame = new JFrame("");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    JPanel panel = new Test();
    frame.add(panel);
    frame.pack();
    frame.setVisible(true);
}

}

Каков предпочтительный способ смешивания и сопоставления jtextfield и jtextareas, сохраняя при этом визуальную гармонию? Теперь я заметил, что текстовое поле имеет синюю подсветку вокруг него, когда в нем находится фокус, в отличие от текстовой области ... еще один источник визуального разрыва.


person I82Much    schedule 16.04.2010    source источник


Ответы (6)


Я знаю, что этот вопрос довольно старый, но чтобы граница для TextArea соответствовала границе TextField:

(myTextArea).setBorder(new JTextField().getBorder());

Это должно дать границу вашему TextArea, как вокруг TextField.

person MikeM    schedule 03.06.2014
comment
Хороший! Но это должен быть новый JTextField().getBorder() - person Baked Inhalf; 31.08.2016

Не уверен, как вы можете решить проблему с границей, но чтобы исправить ситуацию с макетом, я бы просто использовал springlayout. Springlayout — это просто способ лучше расположить ваши элементы в JPanel. Подробнее об этом можно узнать в Руководстве по Java Sun.

В частности, вы используете его, устанавливая, где вы хотите, чтобы ваши северные, южные, западные и восточные границы каждого элемента. Для этого вам нужно будет сначала убрать вызовы лейблов из добавления, чтобы каждый из них мог быть назван. Итак, вместо:

add(new JLabel("Text field:"));

Do:

JLabel myLabelName = new JLabel("Text field:");
add(myLabelName);

Для каждого из ваших элементов (JLabels, JTextAreas и JTextField). Как только это будет сделано, вы можете легко настроить макет.

Springlayout layout = new SpringLayout();
setLayout(layout);

Затем для каждого из элементов вы должны установить любые границы, которые вы хотите. Они должны быть в определенном порядке Юг, Север, Запад, затем Восток. Хотя вам не обязательно использовать все четыре границы, если вы этого не хотите. Вот пример того, как настроить первую текстовую область, верхнюю.

layout.putConstraint(SpringLayout.NORTH, FirstTextAreaName, 10, SpringLayout.NORTH, this);
layout.putConstraint(SpringLayout.WEST, FirstTextAreaName, this.getWidth()/2, SpringLayout.WEST, this);
layout.putConstraint(SpringLayout.EAST, FirstTextAreaName, -10, SpringLayout.EAST, this);

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

layout.putConstraint(SpringLayout.NORTH, SecondTextAreaName, 10, SpringLayout.SOUTH, FirstTextAreaName);

Вторая строка в приведенном выше примере устанавливает восточную сторону текстовой области так, чтобы она начиналась на полпути через главную панель. Последняя, ​​третья строка устанавливает восточную сторону текстовой области на 10 пикселей от восточной стороны вашей основной панели.

person Kyra    schedule 16.04.2010

Я знаю, что MiGLAyout (который мне очень нравится, кстати) имеет возможность специальной обработки для визуального выравнивания по сравнению со строгим выравниванием пикселей. Возможно, вы столкнулись с этим... Для этого используется идентификатор модуля 'al', но мне не приходилось его использовать, поэтому я не могу привести примеры. Вероятно, стоит скачать пример проекта МиГа и посмотреть, есть ли у них такая же проблема с выравниванием (я уверен, что у них есть панели, похожие на вашу).

Что бы это ни стоило, мы довольно часто смешиваем текстовые поля и области на одной и той же панели и не сталкиваемся с этим... Мы делаем должны установить границу области прокрутки такой же, как граница текстового поля, предложенная Ноэлем Анг.

Кроме того, вместо того, чтобы указывать ограничения в конструкторе макета, мы обычно указываем их при добавлении каждого компонента - не уверен, имеет ли это значение или нет...

person Kevin Day    schedule 17.04.2010

Для проблемы макета попробуйте columnConstraints значение [right][fill] вместо [right][left].

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

setLayout(new MigLayout(
        "wrap 2",
        "[right][fill]"
        ));

JTextField textField;
JScrollPane scrollPane;

add(new JLabel("Text field:"));
textField = new JTextField(NUM_CHARACTERS_WIDTH);
textField.setBorder( new EtchedBorder( EtchedBorder.LOWERED ) );
add(textField);

add(new JLabel("No scrollpane text area:"));
add(new JTextArea(NUM_ROWS, NUM_CHARACTERS_WIDTH));

add(new JLabel("Scrollpane text area:"));
scrollPane = new JScrollPane(new JTextArea(NUM_ROWS, NUM_CHARACTERS_WIDTH));
scrollPane.setBorder( new EtchedBorder( EtchedBorder.LOWERED ) );
add(scrollPane);

add(new JLabel("Text field:"));
textField = new JTextField(NUM_CHARACTERS_WIDTH);
textField.setBorder( new EtchedBorder( EtchedBorder.LOWERED ) );
add(textField);

Идентичные границы

Если вы не можете заставить MigLayout выровнять ваши компоненты, рассмотрите возможность использования java.awt.GridBagLayout:

import static java.awt.GridBagConstraints.*;

setLayout( new GridBagLayout() );

GridBagConstraints leftCons = new GridBagConstraints();
leftCons.anchor = NORTHEAST;
leftCons.fill = NONE;
leftCons.weightx = 1.0;
leftCons.gridy = RELATIVE;
leftCons.gridx = 0;
leftCons.insets = new Insets( 4, 8, 4, 8 );

GridBagConstraints rightCons = new GridBagConstraints();
rightCons.anchor = NORTHWEST;
rightCons.fill = HORIZONTAL;
rightCons.weightx = 1.0;
rightCons.gridy = RELATIVE;
rightCons.gridx = 1;
rightCons.insets = leftCons.insets;

add(new JLabel("Text field:"), leftCons);
add(new JTextField(NUM_CHARACTERS_WIDTH), rightCons);

add(new JLabel("No scrollpane text area:"), leftCons);
add(new JTextArea(NUM_ROWS, NUM_CHARACTERS_WIDTH), rightCons);

add(new JLabel("Scrollpane text area:"), leftCons);
add(new JScrollPane(new JTextArea(NUM_ROWS, NUM_CHARACTERS_WIDTH)), rightCons);

add(new JLabel("Text field:"), leftCons);
add(new JTextField(NUM_CHARACTERS_WIDTH), rightCons);
person Noel Ang    schedule 16.04.2010
comment
[Заполнить] помогает. Однако размер по-прежнему не идеален для Mac OSX: grab.by/3O9U - person I82Much; 16.04.2010
comment
Возможно, более гибкая альтернатива состоит в том, чтобы принять предпочтительную границу одного типа компонента и применить ее к другому; например, textField.setBorder(scrollPane.getBorder()). - person Noel Ang; 16.04.2010
comment
Подумайте о том, чтобы попробовать java.awt.GridBagLayout. См. мой измененный ответ для получения дополнительной информации о коде. - person Noel Ang; 16.04.2010

Прежде всего +1 за снимки экрана. Поскольку вы используете Mac, пробовали ли вы Quaqua Look And Feel? Он правильно отображает текстовые поля/области.

person ring bearer    schedule 19.04.2010

Ответ заключается в том, что разработчики MiG Layout работают над исправлением своей следующая версия.

Привет,

У Apple есть неприятная привычка компенсировать ущерб по умолчанию и не позволять разработчику решать. Это тот случай, когда они добавили границу, чтобы сделать ее визуально более похожей на OS X. Это должен быть выбор менеджера компоновки...

MigLayout может компенсировать подобные визуальные ограничения, но это делается только для JTabbedPane в Windows XP. Я не уверен, что это можно сделать на 100% хорошо в OS X. Я должен проверить. Мы не хотим, чтобы текстовое поле просто вырастало до границ.

Я добавил это в список задач для следующей версии.

person I82Much    schedule 22.04.2010