swing и обновление панели
Далее, принцип обновления какой-то странный. Должно быть достаточно
public void revalidateВыделение мое. Т.е. 3-й пункт вообще лишний. У меня все работает и в варианте с JScrollPane и с обычной панелью (все компоненты нормально отрисовываются и обновляются). Пример (естественно без PanelBuilder, так как не известно, что это такое):
Supports deferred automatic layout.
Calls invalidate and then adds this component's validateRoot to a list of components that need to be validated. Validation will occur after all currently pending events have been dispatched. In other words after this method is called, the first validateRoot (if any) found when walking up the containment hierarchy of this component will be validated. By default, JRootPane, JScrollPane, and JTextField return true from isValidateRoot.
This method will automatically be called on this component when a property value changes such that size, location, or internal layout of this component has been affected. This automatic updating differs from the AWT because programs generally no longer need to invoke validate to get the contents of the GUI to update.
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
public class GuiTest {
private static final boolean USE_SP = true;
int count;
JPanel content;
JScrollPane jsp;
JPanel builder;
JButton goButton;
void invokeAndShowGui {
JFrame mainFrame = new JFrame("MainFrame");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setLayout(new BorderLayout;
builder = new JPanel;
builder.setLayout(null);
if (USE_SP) {
jsp = new JScrollPane;
mainFrame.add(jsp, BorderLayout.CENTER);
jsp.setViewportView(builder);
} else {
content = new JPanel(new BorderLayout;
mainFrame.add(content, BorderLayout.CENTER);
content.add(builder, BorderLayout.CENTER);
}
goButton = new JButton("Add");
mainFrame.add(goButton, BorderLayout.PAGE_END);
goButton.addActionListener(new ActionListener {
public void actionPerformed(ActionEvent e) {
builder.removeAll;
count++;
builder.setMinimumSize(new Dimension(30 * count, 30 * count;
builder.setSize(new Dimension(30 * count, 30 * count;
for (int i = 0; i < count; i++) {
JButton tmp = new JButton(Integer.toString(i;
tmp.setBounds(i * 30, i * 30, 30, 30);
builder.add(tmp);
}
builder.setPreferredSize(new Dimension(30 * count, 30 * count;
builder.setMinimumSize(new Dimension(30 * count, 30 * count;
// builder.validate;
//builder.repaint;
// if (USE_SP)
// jsp.validate;
// else
// content.validate;
}
});
mainFrame.pack;
mainFrame.setSize(new Dimension(640, 480;
mainFrame.setVisible(true);
}
public static void main(String [] args) {
final GuiTest gui = new GuiTest;
SwingUtilities.invokeLater(new Runnable {
public void run {
gui.invokeAndShowGui;
}
});
}
}
Так что стоило бы Вам привести еще и минимальный пример, демонстрирующий проблему.
Какие есть методы борьбы с такой штуковиной? Почему скролл так плохо влияет на панель?Методов борьбы два: использовать метод fixPanelBuilder класса MegaBugFixer либо начать корректно использовать компоненты swing (в том числе, панель). Выбор метода зависит от причины. Скролл не плохо влияет на панель, вероятно панель написана без выполеннения контрактов для компонентов swing или используется неправильно.
Хотя при обновлении панели я пыталась обновлять и сам скролл.
А как скролл обновлялся? Может быть, стоило обновить его Viewport?
P.S. А вообще, этот ваш PanelBuilder поддерживает отчуждение его панели getPanel? А то на content по Вашим словам лежал PanelBuilder, а на JScrollPane вы его внутреннюю панель класть пытаетесь.
web-страница ). В вашем примере PanelBuilder тоже работает. Я использую эту библиотеку,так как ее layout кажется мне наиболее удобным.
Сейчас путем некоторых изменений я добилась того, что вижу обновление страницы, но пока проблема с размером скролла .
PanelBuilder это компонент библиотеки jgoodies( Сейчас путем некоторых изменений я добилась того, что вижу обновление страницы, но пока проблема с размером скролла .
В вашем примере PanelBuilder тоже работает.... Сейчас путем некоторых изменений я добилась того, что вижу обновление страницы, но пока проблема с размером скролла .А пример кода, который не работает, увидеть можно? По нему хоть можно было бы сказать, где ошибка. А так - только гадать: ошибка вроде бы есть, а вот где - не понятно.
Я использую эту библиотеку,так как ее layout кажется мне наиболее удобным.В качестве оффтопика - а что не получилось сделать стандартными Layout Manager'ами?
PanelBuilder builder = new PanelBuilder(layout);
JScrollPane pane = new JScrollPane;
pane.setViewportView(builder.getPanel;
Основная панель
JPanel content = new JPanel(new BorderLayout;
content.add(pane, BorderLayout.CENTER);
вот метод который обновляет содержимое панели. раскладку компонент максимально упростила, но суть остается та же.
private void showCharacteristics(ArrayList data) {
RowSpec rowSpec = new RowSpec("FN");
CellConstraints cc = new CellConstraints;
int line = 0;
builder.getPanel.removeAll;
for (int i = 0; i < data.size; i++) {
builder.appendRow(rowSpec);
line++;
builder.addLabel("Label " + i, cc.xy(1, line;
builder.add(new JTextField cc.xy(3, line;
}
//здесь пыталась устанавливать размер скролла, но он принимал нужный размер только в первый раз, при появлении.
content.validate;
}
Стандартные лэауты я тоже использую, но очень не люблю GridBagLayout. а FormLayout по моему тоже обладает неплохими возможностями, а вот в использовании мне он кажется удобнее.
http://www.jgoodies.com/downloads/libraries.html. В нем как раз определены все необходимые в вашем примере классы.
Для запуска пришлось изменить строки
FormLayout layout = new FormLayout("LN ,10px,FN") и
RowSpec rowSpec = new RowSpec("FN")
так как при запуске программы происходил IllegalArgumentException: Invalid unit name 'ln'. Must be one of: px, dlu, pt, mm, cm, in, пришлось посмотреть документацию и немного изменить строку инициализации. Возможно, Вы используете немного другую библиотеку (например, из коммерческой версии, если такая есть, или другой версии в которой возможности класса немного расширены.
В результате получился код, который все равно работает
Специально сделал не только увеличение, но и уменьшение количества элементов. JTextField'у указывается длина, чтобы он был чуть больше, чем для нуля символов, но код будет работать нормально и без указания аргумента конструктора.
Вы в
Может быть, в параметрах что-то не то приходит и в результате отображается не то, что предполагалось?
Кстати, глючок маленький был замечен - не совсем корректно перерисовывается панель при добавлении новых компонентов. Workaround в коде помечен, можно попробовать без него и увидеть, что происходит. Глючок в библиотеке, так как аналогичный код с GridBagLayout работает без Workaround'а:
Посмотрел возможности библиотеки, в принципе, при регулярном размещении FormLayout действительно будет удобнее в использовании да и кода в типичных случаях (для форм и т.п.) получается меньше. Просто с подозрением отношусь к нестандартным библиотекам которые делают вещи, которые можно сделать и стандартными средствами, при этом имеют большой объем, что приводит к большой вероятности ошибки. В данном же случае библиотечка оказалась маленькой и с открытым кодом, что для нее является большим плюсом.
С примером кода стало гораздо лучше, но все еще не совсем понятно. Скачал библиотеку JGoodies Forms со страницы Для запуска пришлось изменить строки
FormLayout layout = new FormLayout("LN ,10px,FN") и
RowSpec rowSpec = new RowSpec("FN")
так как при запуске программы происходил IllegalArgumentException: Invalid unit name 'ln'. Must be one of: px, dlu, pt, mm, cm, in, пришлось посмотреть документацию и немного изменить строку инициализации. Возможно, Вы используете немного другую библиотеку (например, из коммерческой версии, если такая есть, или другой версии в которой возможности класса немного расширены.
В результате получился код, который все равно работает
package test;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;
import com.jgoodies.forms.layout.RowSpec;
public class GuiTest {
private static final boolean USE_SP = true;
int count;
JPanel content;
JScrollPane jsp;
JButton goButton;
FormLayout layout;
PanelBuilder builder;
void invokeAndShowGui {
JFrame mainFrame = new JFrame("MainFrame");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setLayout(new BorderLayout;
layout = new FormLayout("L:D, 10px, F:D");
builder = new PanelBuilder(layout);
content = new JPanel(new BorderLayout;
mainFrame.add(content, BorderLayout.CENTER);
jsp = new JScrollPane;
jsp.setViewportView(builder.getPanel;
content.add(jsp, BorderLayout.CENTER);
goButton = new JButton("Add");
mainFrame.add(goButton, BorderLayout.PAGE_END);
goButton.addActionListener(new ActionListener {
public void actionPerformed(ActionEvent e) {
builder.getPanel.removeAll;
RowSpec rowSpec = new RowSpec("F:D");
CellConstraints cc = new CellConstraints;
int line = 0;
count++;
if (count > 30)
count = 10;
for (int i = 0; i < count; i++) {
builder.appendRow(rowSpec);
line++;
builder.addLabel("Label " + i, cc.xy(1, line;
builder.add(new JTextField(20 cc.xy(3, line;
}
content.validate;
//WORKAROUND for invalid repaint, don't disable ;):
content.repaint;
}
});
mainFrame.pack;
mainFrame.setSize(new Dimension(640, 480;
mainFrame.setVisible(true);
}
public static void main(String [] args) {
final GuiTest gui = new GuiTest;
SwingUtilities.invokeLater(new Runnable {
public void run {
gui.invokeAndShowGui;
}
});
}
}
Специально сделал не только увеличение, но и уменьшение количества элементов. JTextField'у указывается длина, чтобы он был чуть больше, чем для нуля символов, но код будет работать нормально и без указания аргумента конструктора.
Вы в
//здесь пыталась устанавливать размер скролла, но он принимал нужный размер только в первый раз, при появлении.пытаетесь изменить размер самого JScrollPane, либо сделать, чтобы обновилось его содержимое?
Может быть, в параметрах что-то не то приходит и в результате отображается не то, что предполагалось?
Кстати, глючок маленький был замечен - не совсем корректно перерисовывается панель при добавлении новых компонентов. Workaround в коде помечен, можно попробовать без него и увидеть, что происходит. Глючок в библиотеке, так как аналогичный код с GridBagLayout работает без Workaround'а:
void invokeAndShowGui1 {
JFrame mainFrame = new JFrame("MainFrame");
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setLayout(new BorderLayout;
layout = new FormLayout("L:D, 10px, F:D");
builder = new PanelBuilder(layout);
content = new JPanel(new BorderLayout;
mainFrame.add(content, BorderLayout.CENTER);
jsp = new JScrollPane;
jsp.setViewportView(builder.getPanel;
content.add(jsp, BorderLayout.CENTER);
goButton = new JButton("Add");
mainFrame.add(goButton, BorderLayout.PAGE_END);
goButton.addActionListener(new ActionListener {
public void actionPerformed(ActionEvent e) {
builder.getPanel.removeAll;
RowSpec rowSpec = new RowSpec("F:D");
CellConstraints cc = new CellConstraints;
int line = 0;
count++;
if (count > 30)
count = 10;
for (int i = 0; i < count; i++) {
builder.appendRow(rowSpec);
line++;
builder.addLabel("Label " + i, cc.xy(1, line;
builder.add(new JTextField(20 cc.xy(3, line;
}
content.validate;
//WORKAROUND for invalid repaint, don't disable ;):
content.repaint;
}
});
mainFrame.pack;
mainFrame.setSize(new Dimension(640, 480;
mainFrame.setVisible(true);
}
Посмотрел возможности библиотеки, в принципе, при регулярном размещении FormLayout действительно будет удобнее в использовании да и кода в типичных случаях (для форм и т.п.) получается меньше. Просто с подозрением отношусь к нестандартным библиотекам которые делают вещи, которые можно сделать и стандартными средствами, при этом имеют большой объем, что приводит к большой вероятности ошибки. В данном же случае библиотечка оказалась маленькой и с открытым кодом, что для нее является большим плюсом.
Оставить комментарий
evgeniy
подскажите, пожалуйста. стоит такая задача: при некотором событии панель должна обновляться и на ней появляются новые компоненты.Сначала она вообще пустая.Изначально у меня была панель PanelBuilder builder, лежащая на JPanel content.
при обновлении принцип действия был такой:
1. builder.getPanel.removeAll;
2. добавление новых компонентов
3. builder.getPanel.validate;
builder.getPanel.repaint;
content.validate;
и все было хорошо. Но понадобилось положить builder.getPanel на JScrollPane, в результате теперь я просто не вижу никаких обновлений. Панель с компонентами как была пуста, такой и остается.
Какие есть методы борьбы с такой штуковиной? Почему скролл так плохо влияет на панель?
Хотя при обновлении панели я пыталась обновлять и сам скролл.
Люди, знающие swing, помогите пожалуйста.