#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);
Это приведет к динамическому изменению размера текстового поля при изменении размера фрейма.