[英]JPanel revalidate and repaint not working properly (Java Swing)
[英]Java Swing repaint and revalidate not always working
我在揮桿和用幾個按鈕更新JPanel時遇到問題。 有時我需要刪除或添加甚至修改某些按鈕。 我創建了一個例程來執行此操作,幾乎沒有對話框和消息框。 事實是,有時(隨機)JPanel無法正確刷新(它沒有按要求刪除按鈕,甚至沒有添加按鈕)。 如果我第二次調用刷新例程(我調用對話框以添加按鈕,然后單擊退出而不添加任何內容),則一切正常。 我不知道為什么,我認為這與計時和需要每個重新繪制或重新驗證方法生效的時間有關,這是因為我嘗試調試程序(帶有eclipse和幾個斷點),並且在調試過程中總是刷新正確。
這是一些代碼(簡體)。
// This method is used when first creating the GUI (the removeAll obviously remove nothing
// I call the revalidate because I re-add the buttons, and I call repaint to have the
// JPanel itself repainted.
public static void repaintServices() {
//services is a JPanel
services.removeAll();
JLabel lbl = new JLabel("SERVIZI");
services.add(lbl);
services.add(Box.createRigidArea(new Dimension(0, 20)));
// ########## SERVICES BUTTONS
Database.connect();
ArrayList<Service> s = Database.listServices();
JPanel btt = new JPanel();
for (int i = 0; i < s.size(); i++) {
JButton b = new JButton(s.get(i).getName().toUpperCase());
if (i % 3 == 0) {
btt = new JPanel();
btt.setLayout(new BoxLayout(btt, BoxLayout.LINE_AXIS));
services.add(btt);
services.add(Box.createRigidArea(new Dimension(0, 10)));
btt.add(b);
} else {
btt.add(Box.createRigidArea(new Dimension(10, 0)));
btt.add(b);
}
}
Database.disconnect();
// ########## END SERVICES BUTTONS
services.add(Box.createVerticalGlue());
services.revalidate();
services.repaint();
}
這是我修改數據庫(以及按鈕列表)的地方
LOG.finest("User ask to add a new Service");
ArrayList<String> result = GUI.showServiceDialog();
if (result.size() > 0) {
if (!"".equals(result.get(0))) {
String name = result.get(0);
Database.connect();
if (Database.addService(name, price, cadence)) {
GUI.showMessage("Servizio aggiunto correttamente");
GUI.repaintServices();
}
Database.disconnect();
} else {
GUI.showErrorMessage("All field necessary!\nNew Service NOT added");
return;
}
}else {
return;
}
這是用於獲取用戶插入的值的方法(使用自定義模式對話框)
public static ArrayList<String> showServiceDialog() {
ArrayList<String> ret = new ArrayList<String>();
JTextField name = new JTextField(15);
JTextField price = new JTextField(5);
JTextField cadence = new JTextField(4);
// NOT USEFUL STUFF, just adding some components. JUMP DOWN TO.....
JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
JPanel pp = new JPanel();
pp.setLayout(new BoxLayout(pp, BoxLayout.LINE_AXIS));
pp.add(new JLabel("Nome:"));
pp.add(Box.createHorizontalStrut(10));
pp.add(name);
p.add(pp);
p.add(Box.createVerticalStrut(10)); // a spacer
pp = new JPanel();
pp.setLayout(new BoxLayout(pp, BoxLayout.LINE_AXIS));
pp.add(new JLabel("Prezzo:"));
pp.add(Box.createHorizontalStrut(10));
pp.add(price);
pp.add(new JLabel("€"));
pp.add(Box.createHorizontalStrut(20));
pp.add(new JLabel("Frequenza:"));
pp.add(Box.createHorizontalStrut(10));
pp.add(cadence);
p.add(pp);
p.add(Box.createVerticalStrut(15));
// .... HERE, following the interesting part.
int result = JOptionPane.showConfirmDialog(window, p, "Inserisci i dati del nuovo servizio", JOptionPane.OK_CANCEL_OPTION);
if (result == JOptionPane.OK_OPTION) {
ret.add(name.getText());
ret.add(price.getText());
ret.add(cadence.getText());
}
return ret;
}
我還有一些其他方法,如刪除,編輯等,但是每種方法的問題(並非正確刷新)都是隨機的,我發布了我擁有的最簡單的部分。
任何想法? (我對GUI的其他部分(如comboBoxes或listBoxes)也遇到相同的問題,該GUI以SwingUtilities.invokeLater啟動)
這里有一些SSCCE代碼,執行時會出現問題:ADD,ADD,REMOVE,ADD
刪除后添加的內容無法正確刷新(如我所說,有時是隨機刷新)。 (請勿觸摸其他任何東西)。 我希望代碼足夠清晰,簡短,我刪除了似乎不涉及的數據庫。
package it.kApps;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class RevalidateRepaintTry {
private static JPanel services;
private static ArrayList<String> s;
public RevalidateRepaintTry() {
s = new ArrayList<String>();
s.add("btt1");
s.add("btt2");
JFrame main = new JFrame();
main.getContentPane().setLayout(new BoxLayout(main.getContentPane(), BoxLayout.PAGE_AXIS));
services = new JPanel();
repaintServices();
JButton b = new JButton("ADD");
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
String add = JOptionPane.showInputDialog("insert new");
s.add(add);
repaintServices();
}
});
JButton bb = new JButton("DEL");
bb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
s.remove(s.size() - 1);
repaintServices();
}
});
main.add(services);
main.add(b);
main.add(bb);
main.setVisible(true);
main.pack();
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String arg[]) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new RevalidateRepaintTry();
}
});
}
public static void repaintServices() {
// services is a JPanel
services.removeAll();
JLabel lbl = new JLabel("SERVIZI");
services.add(lbl);
services.add(Box.createRigidArea(new Dimension(0, 20)));
// ########## SERVICES BUTTONS
JPanel btt = new JPanel();
for (int i = 0; i < s.size(); i++) {
JButton b = new JButton(s.get(i));
if (i % 3 == 0) {
btt = new JPanel();
btt.setLayout(new BoxLayout(btt, BoxLayout.LINE_AXIS));
services.add(btt);
services.add(Box.createRigidArea(new Dimension(0, 10)));
btt.add(b);
} else {
btt.add(Box.createRigidArea(new Dimension(10, 0)));
btt.add(b);
}
}
// ########## END SERVICES BUTTONS
services.add(Box.createVerticalGlue());
services.revalidate();
services.repaint();
}
}
我覺得布局管理器有問題...
就個人而言,我將從使用其他布局管理器開始。
JPanel
默認情況下使用FlowLayout
,它具有令人敬畏的副作用,即不會“包裝”組件的擴展超出父容器的水平寬度。
雖然我知道Box
可以與其他布局管理器一起使用,但是它被設計為可以與BoxLayout
,所以如果它不能按照您想要的方式工作,我也不會感到驚訝。
public class RevalidateRepaintTry {
private static JPanel services;
private static ArrayList<String> s;
public RevalidateRepaintTry() {
s = new ArrayList<String>();
s.add("btt1");
s.add("btt2");
JFrame main = new JFrame();
main.getContentPane().setLayout(new BoxLayout(main.getContentPane(), BoxLayout.PAGE_AXIS));
services = new JPanel();
repaintServices();
JButton b = new JButton("ADD");
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
String add = JOptionPane.showInputDialog("insert new");
s.add(add);
repaintServices();
}
});
JButton bb = new JButton("DEL");
bb.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
s.remove(s.size() - 1);
repaintServices();
}
});
main.add(services);
main.add(b);
main.add(bb);
main.setVisible(true);
main.pack();
main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String arg[]) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new RevalidateRepaintTry();
}
});
}
public static void repaintServices() {
// services is a JPanel
services.removeAll();
JLabel lbl = new JLabel("SERVIZI");
JPanel view = new JPanel(new GridBagLayout());
JScrollPane scroll = new JScrollPane(view);
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 0;
gbc.gridy = 0;
view.add(lbl, gbc);
// ########## SERVICES BUTTONS
for (int i = 0; i < s.size(); i++) {
JButton b = new JButton(s.get(i));
if (i % 3 == 0) {
gbc.gridy++;
gbc.gridx = 0;
} else {
gbc.gridx++;
}
view.add(b, gbc);
}
// ########## END SERVICES BUTTONS
view.add(Box.createVerticalGlue());
services.add(scroll);
services.revalidate();
services.repaint();
}
}
注意,我放入了JScrollPane
,可能不是必需的
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.