2

我在使用几个按钮来摆动和更新 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 的其他部分也有同样的问题,比如组合框或列表框,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();
}
}
4

1 回答 1

1

我感觉这是布局管理器的问题...

就个人而言,我会从使用不同的布局管理器开始。

JPanel默认情况下使用 a 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,它可能不是必需的

于 2012-10-13T21:21:54.250 回答