Создание текстового поля, которое динамически изменяет свою ширину

#java #swing #jtextfield

#java #swing #jtextfield

Вопрос:

Я создаю то, что в основном представляет собой панель инструментов, содержащую поле поиска и несколько кнопок. Я бы хотел, чтобы поле поиска увеличивалось в размере (только по ширине), когда родительский контейнер становится шире, например, когда пользователь настраивает разделенную панель. В настоящее время текстовое поле и кнопки останутся прежнего размера, а пробелы добавляются с обеих сторон по мере расширения контейнера. Я могу добиться этого растущего эффекта, используя a BorderLayout в контейнере и поместив кнопки на LINE_END и текстовое поле в CENTER . Проблема, с которой я сталкиваюсь, заключается в том, что текстовое поле теперь становится выше стандартного текстового поля и выглядит уродливо. Такое поведение имеет смысл, поскольку BorderLayout менеджер выделит все дополнительное пространство (включая вертикальное и горизонтальное пространство) для CENTER текстового поля. Я пытался ограничить этот вертикальный рост, установив максимальный размер текстового поля, но BorderLayout это не соблюдается.

Вот что у меня получилось:

 final JTextField searchField = new JTextField("Enter your search terms");
searchField.setMaximumSize(new Dimension(Integer.MAX_VALUE, 25));
final JPanel controls = new JPanel(new BorderLayout());
controls.add(searchField, BorderLayout.CENTER);
controls.add(new JPanel(){{
    add(new JButton("Search")); add(new JButton("I'm Feeling Lucky"));
}}, BorderLayout.LINE_END);
  

Казалось бы, такое поведение является общепринятым, и его должно быть легко реализовать, но мне не повезло после просмотра всех руководств Oracle / Sun и результатов поиска Google.

У кого-нибудь есть какие-либо решения для этого? Мне нужно придерживаться стандартных компонентов Java Swing — пожалуйста, никаких сторонних библиотек.

Спасибо!

Ответ №1:

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

Вот пример использования gridbaglayout для этого вопроса…

 import java.awt.BorderLayout;

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

public class GridBagLayoutExample extends JFrame {

    GridBagLayoutExample() {
        initUI();
    }


    private void initUI() {
        final JTextField searchField = new JTextField("Enter your search terms"); 
        final JPanel controls = new JPanel(new GridBagLayout()); 
        GridBagConstraints c = new GridBagConstraints();
        c.weightx=1.0;
        c.fill=GridBagConstraints.HORIZONTAL;
        controls.add(searchField,c); 
        controls.add(new JPanel(){
            {     
            add(new JButton("Search")); add(new JButton("I'm Feeling Lucky")); }}); 
        setLayout(new BorderLayout());
        add(controls, BorderLayout.NORTH);
        pack();
    }


    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new GridBagLayoutExample().setVisible(true);

            }
        });
    }
}
  

Комментарии:

1. Не могли бы вы показать, как использовать GridBagLayout для достижения этого эффекта? Это было бы хорошим введением в изучение этого менеджера компоновки.

2. Отлично! Это было намного менее болезненно, чем я ожидал; спасибо за вашу помощь.

3. как я уже говорил, gridbaglayout необходим каждому программисту swing.

4. GridBagLayout только для мазохистов 😉 Доступны сторонние LayoutManagers, которые являются более мощными и более простыми в использовании, например, любой из «большой тройки» FormLayout, MigLayout, DesignLayout

5. Здесь я согласен с kleopatra. Я серьезно продвинулся в любом макете по умолчанию, даже в Grid или GridBag-менеджерах компоновки после проекта, где от меня требовалось изменять количество и положение элементов в зависимости от выбора пользователя. Макеты по умолчанию просто антидинамичны по своей природе. Для меня полезным здесь был TableLayout. Кстати, кто-нибудь знает, что случилось с этим проектом, недавно я не мог попасть на их страницу ?! Удачи, Боро.

Ответ №2:

это проблема из двух частей:

a) все xxSize (xx = min / max / pref) являются простыми подсказками для LayoutManager. У каждого LayoutManager есть свое собственное поведение, если / как / когда он соблюдает эти подсказки и если / как / когда он нарушает одну или несколько, если общее пространство больше или меньше, чем соответствовало бы сумме pref для всех компонентов в контейнере. Нет другого способа, кроме как узнать, что что делает (документация есть … ehem … неоптимально)

b) JTextField немного сумасшедший, позволяя его высоте расти бесконечно, если позволяет пространство. Подразумевая, что даже LayoutManagers, которые учитывают max (например, BoxLayout), не имеют возможности это сделать, max является целым числом.MAX_VALUE (или Short.MAX? забыл). Чтобы оно работало нормально, создайте подкласс и переопределите maxSize, чтобы вернуть значение pref height:

 @Override
Dimension getMaximumSize() {
   Dimension max = super.getMaximumSize();
   max.height = getPreferredSize().height; 
   return max;
}
  

Ответ №3:

Вы должны уметь использовать горизонтальное BoxLayout.

 searchField.setMaximumSize(new Dimension(Integer.MAX_VALUE, 25)); 
  

Вы не должны угадывать высоту текстового поля.

 Dimension d = searchField.getPreferredSize();
d.width = Integer.MAX_VALUE;
searchField.setMaximumSize(d);
  

Я знаю, вы сказали, что не хотите использовать сторонние библиотеки, но в качестве дополнительного примечания вы, возможно, захотите взглянуть на текстовое поле Prompt. Это позволяет отображать сообщение, которое исчезнет, когда вы начнете вводить текст в текстовом поле.

Комментарии:

1. Я еще раз взгляну на BoxLayout . Возможно, вы могли бы предоставить немного больше информации, чем эта?

2. вы определенно знаете лучше, чем предлагаете использовать api, который никогда не используется при разработке приложений 🙂 setXXSize запрещен всегда

Ответ №4:

Использование BoxLayout.

 JTextField search_field = new JTextField("Enter search term");
JPanel panel = new JPanel();
panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
panel.add(search_field);
  

Это приведет к динамическому изменению размера текстового поля при изменении размера фрейма.