Java Swing重绘和重新验证并不总是有效

时间:2012-10-13 18:02:25

标签: java swing validation layout repaint

我在使用几个按钮更新JPanel时出现问题。有时我需要删除或添加甚至修改一些按钮。我已经创建了一个例程,只需要很少的对话框和消息框。事实是,有时(随机)JPanel无法正确刷新(它不会按要求删除按钮,甚至不添加它)。如果我第二次调用刷新例程(我调用对话框添加一个按钮,然后单击exit而不添加任何东西)一切顺利。我不知道为什么,我认为这是关于时间和需要每个重绘或重新验证方法有效的时间,这个考虑是因为我试图调试程序(使用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;
}

这是用于获取用户插入的值的metod(使用自定义模式对话框)

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代码,问题出现了: 添加,添加,删除,添加

删除后的添加不能正确刷新(有时,有时是随机的,正如我所说)。 (没有接触任何其他东西)。我希望代码足够清晰,足够短,我删除了似乎没有涉及的数据库。

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();
}
}

1 个答案:

答案 0 :(得分:1)

我觉得布局管理器存在问题......

就个人而言,我首先要使用不同的布局管理器。

默认情况下,

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,可能不需要