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;

}

削除、編集などの他の方法がいくつかありますが、問題(正しく更新されない)はこの方法のそれぞれでランダムに発生します。私が持っている最も単純な部分を投稿しました。

何か案が?(comboBoxesやlistBoxesなどのGUIの他の部分でも同じ問題があります。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();
}
}
4

1 に答える 1

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

注、私は a を投げましたがJScrollPane、おそらく必須ではありません

于 2012-10-13T21:21:54.250 に答える