0

I work on a Swing application displaying different "sub"JFrames from a main JFrame. I have an issue on a specific "sub"JFrame called FrameStratigraphie.

For others "sub"JFrames when I am done with them I just dispose them and recreate them later if needed. But this one, when I dispose it and recreate it, the action listener triger X times and X is the number of times I created this frame.

Here is how I set my action listener :

        bouton.addActionListener(lambda -> dispose());

I am really new to lambda expressions so the issue could come from here.

I tried to work around by just setVisible(false) my FrameStratigraphie and try to [removeAll + revalidate + repaint] but if I open any other "sub"JFrame and then try to recreate it, the frame is just grey. Like no component is added to it. (But I can still see the correct FrameStratigraphie for 0.1 second before it is removeAll() ). I'd like to know why.

To summarize :

  • Why my actionListener method is triggered multiple times if I do JFrame.dispose()

  • Why nothing appear after setting my frame to visible(false)

This is my first post on stackoverflow and I am sorry if I have done any mistake on appearance, spelling or relevance and for my french comments in my code...

Thank you in advance for any information, track, advice, comment or answer related to my issue.

Stratigraphie.java



    package vue.forage.quart;

    import java.util.ArrayList;

    import javax.swing.JButton;
    import javax.swing.JLabel;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;

    import vue.AbstractFrame;
    import vue.AbstractFrame2;
    import vue.FrameStratigraphie;
    import vue.forage.Quart;

    public class Stratigraphie{

        /**
         * 
         */
        private static FrameStratigraphie frame;
        private static final long serialVersionUID = 1L;
        private static JTextField textField = new JTextField(5);
        private static JTextField textField2 = new JTextField(5);
        private static JTextField textField3 = new JTextField(10);
        private static JLabel label = new JLabel();
        private static JLabel label2 = new JLabel();
        private static JLabel label3 = new JLabel();
        private static JLabel label4 = new JLabel();
        private static JLabel label5 = new JLabel();
        private static JLabel label6 = new JLabel();
        private static JLabel label7 = new JLabel();
        private static JTextArea textArea = new JTextArea();
        private static JButton bouton = new JButton();
        private static String[] couchesPrecedentes = new String[3];
        private static ArrayList liste; 

        public Stratigraphie(FrameStratigraphie frameStratigraphie) {
            frame = frameStratigraphie;
            liste = Quart.getStrat();
            bouton.addActionListener(lambda -> dispose());
        }

        public void stratigraphie() {
            getInit();
            frame.getContentPane().removeAll();
            frame.setTitle("Stratigraphie");

            if (couchesPrecedentes != null) {
                frame.setLabel(0, 0, couchesPrecedentes[0], label4); //recupere la valeur finale de la derniere couche
                frame.setLabel(1, 0, couchesPrecedentes[1], label5);
                frame.setLabel(2, 0, couchesPrecedentes[2], label6);
            }
            frame.setLabel(0, 1, "Profondeur initiale", label);
            frame.setLabel(1, 1, "Profondeur finale", label2);
            frame.setTextAreaAsLabel(2, 1, "Description stratigraphique", textArea);
            if(liste.size() > 0)
                frame.setLabel(0, 2, Integer.toString(liste.get(liste.size()-1).getFinale()), label7);
            else
                frame.setTextField(0, 2, "", textField);
            frame.setTextField(1, 2, "", textField2);
            frame.setTextField(2, 2, "", textField3);
            frame.setBouton("Retour", 0, 3, bouton);

            frame.getContentPane().revalidate();
            frame.getContentPane().repaint();
        }

        public static void getInit()//Sorry, in this function I use html
     //tags in order to format my JLabel so everything do not appear on stack
    // overflow because I am bad with HTML. But I do not think this function
    // contain anything important for my issue.
        {
            couchesPrecedentes[0] = "";
            couchesPrecedentes[1] = "";
            couchesPrecedentes[2] = "";
            for (int i = 0; i " + Integer.toString(liste.get(i).getInitiale());
                    couchesPrecedentes[1] += "
" + Integer.toString(liste.get(i).getFinale()); couchesPrecedentes[2] += "
" + liste.get(i).getDescription(); } } couchesPrecedentes[0] += ""; couchesPrecedentes[1] += ""; couchesPrecedentes[2] += ""; } public void dispose() { System.out.println("on a un dispose"); Strate strate = null; if(liste.size() > 0) strate = new Strate(Integer.parseInt(label7.getText()), Integer.parseInt(textField2.getText()),textField3.getText()); else strate = new Strate(Integer.parseInt(textField.getText()), Integer.parseInt(textField2.getText()),textField3.getText()); Quart.addStrate(strate); frame.setVisible(false); // frame.dispose(); Quart.visible(true); } public static void visible(boolean bool) { frame.setVisible(bool); } }

How I start my FrameStratigraphie



        private static void ouvreStratigraphie(){
    //      if(frameStratigraphique == null)
                frameStratigraphique = new FrameStratigraphie();
    //      else{
    //          frameStratigraphique.getStratigraphie().stratigraphie();
    //          frameStratigraphique.setVisible(true);
    //      }
            frame.setVisible(false);
        }

FrameStratigraphie



    package vue;

    import vue.forage.quart.Stratigraphie;

    public class FrameStratigraphie extends AbstractFrame2 {

        private Stratigraphie stratigraphie = new Stratigraphie(this);
        public FrameStratigraphie() {
            super();
            stratigraphie.stratigraphie();
        }

        public Stratigraphie getStratigraphie()
        {
            return stratigraphie;
        }
    }

AbstractFrame2



    package vue;

    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Panel;

    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JTextArea;

    import model.personnel.Personne;
    //frame secondaire dont héritent les JFrame secondaires (FrameCommentaire etc..)

    public abstract class AbstractFrame2 extends AbstractFrame{

        private static final long serialVersionUID = 1L;

        public AbstractFrame2() {
            super(new JPanel(new GridBagLayout()),new GridBagConstraints());
            dimension = Frame.initDimension();
            this.setSize(dimension[0], dimension[1]);
            this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            this.setLocationRelativeTo(null);
            this.setContentPane(pan);
            this.setVisible(true);
            c.weightx = 1;
        }
    }

AbstractFrame



    package vue;

    import java.awt.Dimension;
    import java.awt.Font;
    import java.awt.GridBagConstraints;
    import java.awt.GridBagLayout;
    import java.awt.Panel;
    import java.awt.TextArea;
    import java.awt.Toolkit;
    import java.awt.image.BufferedImage;
    import java.io.File;
    import java.io.IOException;
    import java.nio.charset.StandardCharsets;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.Date;
    import java.util.stream.Stream;

    import javax.imageio.ImageIO;
    import javax.swing.DefaultComboBoxModel;
    import javax.swing.Icon;
    import javax.swing.ImageIcon;
    import javax.swing.JButton;
    import javax.swing.JComboBox;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JPanel;
    import javax.swing.JPasswordField;
    import javax.swing.JSpinner;
    import javax.swing.JTextArea;
    import javax.swing.JTextField;
    import javax.swing.JSpinner.DateEditor;

    //modele de frame qui regroupe toutes les methodes de placement de composants

    public abstract class AbstractFrame extends JFrame {

        protected static int[] dimension;
        protected static JPanel pan;
        protected static GridBagConstraints c;
        protected static BufferedImage bufferedImage;

        public AbstractFrame(JPanel panel, GridBagConstraints g)
        {
            pan = panel;
            c = g;
        }

        public static int[] initDimension() {
            Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
            int[] dim = new int[2];
            dim[1] = (int) dimension.getHeight() / 2;
            dim[0] = (int) dimension.getWidth() / 2;
            return dim;
        }

        public void setTime(int x, int y, JSpinner spinner, DateEditor timeEdit){
            spinner.setEditor(timeEdit);
            spinner.setValue(new Date());
            c.gridx = x;
            c.gridy = y;
            pan.add(spinner, c);
        }

        public void setLabel(int x, int y, String text, JLabel component) {
            c.gridx = x;
            c.gridy = y;
            component.setText(text);
            pan.add(component, c);
        }

        public void setTextAreaAsLabel(int x, int y, String text, JTextArea component){
            component.setText(text);
            component.setFont(new Font("Serif", Font.ITALIC, 16));
            component.setLineWrap(true);
            component.setWrapStyleWord(true);
            component.setOpaque(false);
            component.setEditable(false);
        }

        public void setImageLabel(int x, int y, String chemin, JLabel component) {
            component.removeAll();
            c.gridx = x;
            c.gridy = y;
            c.weightx = 1;
            c.gridwidth = GridBagConstraints.REMAINDER;
            try {
                bufferedImage = ImageIO.read(new File(chemin));
            } catch (IOException e) {
                System.out.println("ERREUR setImageLabel chemin " + chemin);
                e.printStackTrace();
            }
            Icon icon = new ImageIcon(bufferedImage);
            component.setIcon(icon);
            pan.add(component, c);
            c.gridwidth = 1;
        }

        public void setBouton(String text, int x, int y, JButton bouton) {
            bouton.setText(text);
            c.gridx = x;
            c.gridy = y;
            pan.add(bouton, c);
        }

        public void setTextField(int x, int y, String text, JTextField component) {
            c.gridx = x;
            c.gridy = y;
            component.setText(text);
            pan.add(component, c);
        };

        public void setPasswordField(int x, int y, JPasswordField component) {
            c.gridx = x;
            c.gridy = y;
            pan.add(component, c);
        }

        public void setTextArea(int x, int y, String text, TextArea component) {
            c.gridx = x;
            c.gridy = y;
            component.setText(text);
            pan.add(component, c);
        }

        public void setComboBox(int x, int y, String chemin, JComboBox combo) {
            Stream streamString = null;
            try {
                streamString = Files.lines(Paths.get(chemin), StandardCharsets.UTF_8);
            } catch (IOException e) {
                System.out.println("setComboBox " + chemin);
                e.printStackTrace();
            }
            String[] choix = streamString.toArray(size -> new String[size]);
            DefaultComboBoxModel model = (DefaultComboBoxModel) combo.getModel();
            model.removeAllElements();
            for (String s : choix) {
                model.addElement(s);
            }
            c.gridx = x;
            c.gridy = y;
            pan.add(combo, c);
        }

        public void setComboBoxString(int x, int y, String[] text, JComboBox combo){
            ((DefaultComboBoxModel)combo.getModel()).removeAllElements();
            for(int i = 0; i )combo.getModel()).addElement(text[i]);
            }
            c.gridx = x;
            c.gridy = y;
            pan.add(combo, c);
        }

        public void setTextArea(String text, int x, int y, JTextArea bouton) {
            bouton.setText(text);
            bouton.setMaximumSize(getPreferredSize());
            c.gridx = x;
            c.gridy = y;
            pan.add(bouton, c);
        }


    }

  • That's a LOT of code, probably no one will read it, instead edit your post and replace that bunch of code with a [Minimal Complete and Verifiable Example](http://stackoverflow.com/help/mcve) which contains the most relevant code but still shows the issue, i.e. make a new project from scratch and try to reproduce the problem there but remove things as not needed validations / colors / buttons / etc that have nothing to do with your problem. This will lead to less confusion and more, faster and better answers – Frakcool Jun 13 '16 at 15:40
  • 1
    Also take a look at [The use of multiple JFrames, Good / Bad practice?](http://stackoverflow.com/questions/9554636/the-use-of-multiple-jframes-good-or-bad-practice) – Frakcool Jun 13 '16 at 15:42
  • Thank you for your advices sir ! The Minimal C. V. example is very helpful. And I did read your second link yet I found that a lot of comments in favor of "Good" were accurate, I may be wrong. – J. Lamandé Jun 13 '16 at 15:57
  • It's a bad practice, instead you could use [Card Layout](https://docs.oracle.com/javase/tutorial/uiswing/layout/card.html) or [JDialog](https://docs.oracle.com/javase/7/docs/api/javax/swing/JDialog.html). Having multiple `JFrame`s will lead to a bad user experience, since he will have multiple icons of your app opened and will be harder to maintain. However, use multiple JFrames when needed and where needed, but keep them to the minimum and use them at your own risk. Sometimes you simply need to use them that way. – Frakcool Jun 13 '16 at 16:05

1 Answers1

2

Every time you create a new Stratagraphie you invoke:

bouton.addActionListener(lambda -> dispose());

All the variables in your Stratagraphie class are static, which means they don't get recreated every time a new instance is created, so you continually keep adding a new ActionListener to the button.

Get rid of all the static variables!!!

Check out examples from the Swing tutorial on creating frames and variables used by the class. The TextDemo from How to Use Text Areas has a simple xample.

camickr
  • 321,443
  • 19
  • 166
  • 288