Установка максимального размера JDialog?
Короткая версия: мне нужно сделать что-то хитрое, чтобы заставить JDialog setMaximumSize() работать?
Полная версия: у меня есть JDialog (менеджер раскладки: BorderLayout), который содержит панель прокрутки и JPanel внизу с кнопками фиксации.
Панель прокрутки содержит JPanel, который динамически создается в другом месте системы.
Я хочу, чтобы диалог динамически изменял размеры вокруг JPanel до определенного размера, а затем начинал увеличивать полосы прокрутки. Это, более или менее, то, что происходит по умолчанию, за исключением того, что максимальный размер соответствует размеру моего монитора.
Я думал, что это то, что сделал метод.setMaximumSize(), унаследованный от java.awt.Component, но установка его, похоже, не имеет никакого эффекта.
Установка предпочтительного размера имеет эффект - но тогда диалоговое окно всегда будет такого размера, несмотря ни на что, что на самом деле не то, что я хочу.
(И эффекты будут такими же, если я установлю свойства максимального / предпочтительного размера на панели прокрутки.)
Я что-то упустил невероятно очевидный? Есть ли какое-то дурацкое взаимодействие JDialog / BorderLayout / MaximumSize, о котором я не знаю?
4 ответа
Сделать элемент панели Scrollable - это то, что нужно. Смотрите также (в дополнение к обучающей ссылке, уже предоставленной Trashgod) запись в блоге Роба
http://tips4java.wordpress.com/2009/12/20/scrollable-panel/
затем:
1) реализовать getPreferredScrollableViewportSize() в терминах, приемлемых для типичного контента (для JList fi это предпочтительное количество отображаемых строк, иначе: visibleRowCount)
2) реализовать сеттеры / геттеры для этих "разумных условий"
Этот дополнительный уровень (координирует "разумные условия") позволяет всем сотрудничающим компонентам делать все возможное, чтобы придумывать надежные подсказки по размеру без недружественных помех, как setXXSize (который никогда не бывает никогда, просто забудьте, что эти методы существуют;)
Как обсуждалось в разделе Размер панели прокрутки, некоторые компоненты могут предоставить полезную информацию о настройке предпочтительного размера области просмотра. setVisibleRowCount()
метод JList
особенно удобно, но даже getViewport().setPreferredSize(…)
может хватить. Естественно, sscce поможет.
Приложение: в качестве конкретного примера, нижеприведенное диалоговое окно изначально имеет размер N- 2 строки. Поскольку больше добавлено, диалог увеличивается, пока число не достигает N. В этот момент полосы прокрутки начинают "расти". В примере используется JList
, но любой Scrollable
компонент должен быть адаптируемым.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.DefaultListModel;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
/** @see http://stackru.com/questions/5759131 */
public class ListDialog {
private static final int N = 12;
private JDialog dlg = new JDialog();
private DefaultListModel model = new DefaultListModel();
private JList list = new JList(model);
private JScrollPane sp = new JScrollPane(list);
private int count;
public ListDialog() {
JPanel panel = new JPanel();
panel.add(new JButton(new AbstractAction("Add") {
@Override
public void actionPerformed(ActionEvent e) {
append();
if (count <= N) {
list.setVisibleRowCount(count);
dlg.pack();
}
}
}));
for (int i = 0; i < N - 2; i++) {
this.append();
}
list.setVisibleRowCount(N - 2);
dlg.add(sp, BorderLayout.CENTER);
dlg.add(panel, BorderLayout.SOUTH);
dlg.pack();
dlg.setLocationRelativeTo(null);
dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dlg.setVisible(true);
}
private void append() {
model.addElement("String " + String.valueOf(++count));
list.ensureIndexIsVisible(count - 1);
}
public static void main(String[] a_args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
ListDialog pd = new ListDialog();
}
});
}
}
Метод pack(), который определяет размер JDialog, зависит от вызова getPreferredSize(), чтобы определить, какой размер использовать.
Если вы создаете подкласс JDialog, вы можете установить максимальный размер, создав подкласс этого метода.
Пример:
@Override
public Dimension getPreferredSize() {
int maxWidth=500;
int maxHeight=300;
Dimension dim=super.getPreferredSize();
if (dim.width>maxWidth) dim.width=maxWidth;
if (dim.height>maxHeight) dim.height=maxHeight;
return dim;
}
Вы должны рассчитать getSize()
от JComponents внутри JScrollPane
просто простой пример
Редактировать: и вызвать JDialog#pack()
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
public class PackDialog {
private JDialog dlg;
private JScrollPane scrollPane;
private JPanel panel;
private JButton btn;
public PackDialog() {
btn = new JButton();
btn.setPreferredSize(new Dimension(300, 30));
btn.addActionListener(new java.awt.event.ActionListener() {
@Override
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnActionPerformed(evt);
}
private void btnActionPerformed(ActionEvent evt) {
int h = panel.getHeight();
h += btn.getHeight();
int w = panel.getWidth();
dlg.setPreferredSize(new Dimension(w, h));
dlg.pack();
}
});
panel = new JPanel();
panel.setPreferredSize(new Dimension(300, 600));
panel.setLayout(new BorderLayout(10, 10));
panel.add(btn, BorderLayout.SOUTH);
scrollPane = new JScrollPane(panel);
dlg = new JDialog();
dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
dlg.setPreferredSize(new Dimension(400, 300));
dlg.add(scrollPane);
dlg.pack();
dlg.setVisible(true);
}
public static void main(String[] a_args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
PackDialog pd = new PackDialog();
}
});
}}