0

I am pretty new in Swing development and I have the following problem using a class that implements the PropertyChangeListener interface.

So I have the following GUI class (I am posting only the interesting section of this class):

public class GUI extends SingleFrameApplication implements PropertyChangeListener {

private MainFrame mainFrame = null;
private static LoginFrame loginFrame;

    @Override
protected void startup() {
    boolean offLine = false;
            showLoginFrame();

    mainFrame = new MainFrame(settings, tasksSettings, logAppender);

    if (OSUtils.isUbuntuPrecisePangolin() || OSUtils.isFedoraBeefyMiracle() || OSUtils.isFedoraSphericalCow()) {
        File mountPointFolder = new File(System.getenv("HOME") + "/connect_drives");
        if (!mountPointFolder.exists())
            mountPointFolder.mkdir();

        mainFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        mainFrame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                if (mainFrame.getState() == JFrame.ICONIFIED)
                    tryToExit();
                else
                    mainFrame.setState(JFrame.ICONIFIED);
            }
        });
    }
}

private void showLoginFrame() {
    loginFrame = new LoginFrame();
    loginFrame.setVisible(true);
    loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // Notify every change to every bound property for that object:
    loginFrame.addPropertyChangeListener(this); 

}

@Override
protected void shutdown() {
    System.out.println("Entered into GUI ---> shutdown()");
    logger.debug("Termino l'applicazione.");
    ulogger.info(Constants.APP_TITLE + "|Arresto "+ Constants.APP_TITLE);
    // FileUtils.saveGeneralLogFile(logAppender.getLogInFile());
    logAppender.saveGeneralLogFile();
    EventBusService.unsubscribe(this);
    if (mainFrame != null)
        mainFrame.setVisible(false);

}
public static void main(String[] args) {

    launch(GUI.class, args);
}

@Override
public void propertyChange(PropertyChangeEvent arg0) {
    System.out.println("GUI SingleFrameApplication ---> propertyChange(): " + arg0.getPropertyName());

    if (arg0.getPropertyName().equals("buttonLogOffClicked")) {
        //System.out.println("GUI SingleFrameApplication ---> richiamo exit");
        //exit();

        mainFrame.OnWindowClose();
        mainFrame.dispose();
        mainFrame = null;

        showLoginFrame();
    }

    if (arg0.getPropertyName().equals("loginResult")) {
        System.out.println("GUI SingleFrameApplication ---> richiamo MainFrame");
        //loginFrame.setVisible(false);
        loginFrame.dispose();
        loginFrame = null;

        showMainFrame();
    }

}

private void showMainFrame() {

    mainFrame = new MainFrame(settings, tasksSettings, logAppender);
    // I add a PropertyChangeListener to the created MainFrame object:
    mainFrame.addPropertyChangeListener(this);
    mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    WindowListener exitListener = new WindowAdapter() {

        @Override
        public void windowClosing(WindowEvent e) {
            System.out.println("GUI SingleFrameApplication --> windowClosing");
            shutdown();
            // mainFrame.setVisible(false);
            /*int confirm = JOptionPane.showOptionDialog(frame,
            "Are You Sure to Close this Application?",
            "Exit Confirmation", JOptionPane.YES_NO_OPTION,
            JOptionPane.QUESTION_MESSAGE, null, null, null);
            if (confirm == JOptionPane.YES_OPTION) {
            System.exit(1);
            }*/
        }
    };

    mainFrame.addWindowListener(exitListener);
    mainFrame.setVisible(true);
}

Then I have the MainFram class that extends a JFrame in which there is a JButton to perform the log out operation, something like this:

public class MainFrame extends JFrame {
    private final Action actionLogOut = new AbstractAction() {
        {
            putValue(Action.NAME, _("log-out"));
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("logOutButton clicked !!!, firePropertyChange() will start");
            // System.exit(0);
            firePropertyChange("buttonLogOffClicked", false, true);
        }
    };

    public MainFrame(Settings settings, TasksSettings tasksSettings, LogAppender logAppender) {
        super();
    ......................
    ......................
    ......................
    header.add(new JButton(actionLogOut));
    ......................
    ......................
    ......................
    }
}

So when my JButton is clicked it is performed this method:

private final Action actionLogOut = new AbstractAction() {
    {
        putValue(Action.NAME, _("log-out"));
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("logOutButton clicked !!!, firePropertyChange() will start");
        // System.exit(0);
        firePropertyChange("buttonLogOffClicked", false, true);
    }
};

infact when I click on the button, in the console, appear to me the output:

"logOutButton clicked !!!, firePropertyChange() will start"

and then I execute the firePropertyChange() method and I would expect that this event was handle by this method of GUI class:

@Override
public void propertyChange(PropertyChangeEvent arg0) {
    System.out.println("GUI SingleFrameApplication ---> propertyChange(): " + arg0.getPropertyName());

    if (arg0.getPropertyName().equals("buttonLogOffClicked")) {
        //System.out.println("GUI SingleFrameApplication ---> richiamo exit");
        //exit();

        mainFrame.OnWindowClose();
        mainFrame.dispose();
        mainFrame = null;

        showLoginFrame();
    }

    if (arg0.getPropertyName().equals("loginResult")) {
        System.out.println("GUI SingleFrameApplication ---> richiamo MainFrame");
        //loginFrame.setVisible(false);
        loginFrame.dispose();
        loginFrame = null;

        showMainFrame();
    }

}

But don't work and seems not enter in the firePropertyChange() method?

Why? What am I missing?

Tnx

Andrea

PM 77-1
  • 12,933
  • 21
  • 68
  • 111
AndreaNobili
  • 40,955
  • 107
  • 324
  • 596
  • now really new, AFAIK did you post an SSCCE – mKorbel Nov 18 '13 at 21:35
  • It seams that [`PropertyChangeListener`](http://docs.oracle.com/javase/tutorial/uiswing/events/propertychangelistener.html) is for "*a component that conforms to the JavaBeans™ specification.*". So [`Property`](http://docs.oracle.com/javase/tutorial/javabeans/writing/properties.html) is used in `JavaBean` context. – PM 77-1 Nov 18 '13 at 21:46
  • @PM77-1, and which things are java beans ? – Sage Nov 18 '13 at 21:51
  • @Sage : `JavaBean` is a Java class that adheres to a certain standard. I believe that the accepted answer in [What is a Java Bean exactly?](http://stackoverflow.com/questions/3295496/what-is-a-java-bean-exactly) post explains it well. Are you saying that `JFrame` itself is a bean? – PM 77-1 Nov 18 '13 at 21:57
  • yes, Components are Beans too. – Sage Nov 18 '13 at 22:02
  • @Sage : But is `JButton` a *property* of `MainFrame`? So anything within a container is a property of a container? – PM 77-1 Nov 18 '13 at 22:08
  • @PM77-1, Nope, a component is not a property of another component. But Every component has their own property: bounds, preferredsize, minimumSize. And Every component has `getXXX()` and `setXXX()` method to get and set their property `xxx`. So we can fire an event on property change and have them listen to it:) – Sage Nov 18 '13 at 22:11
  • @Sage : So as long as we `fire` from **within** the class `listener` attached to, the rest doesn't matter, right? – PM 77-1 Nov 18 '13 at 22:19

1 Answers1

1

When you are calling firePropertyChange from the MainFrame context it is firing for the MainFrame, which can actually listen to it's property change event. But instead you have added listener to the login frame, using loginFrame.addPropertyChangeListener(this); loginframe will listen to the change, if a change event is fired by it's own firePropertyChange function. However you can call loginFrame.firePropertyChange("buttonLogOffClicked", false, true); from the actionPerformed() function of actionLogOut Action, in MainFrame class.

Edit:

  1. Try passing the instance of LoginFrame to MainFrame instance constructor, you have created to work with.

  2. Or, In your GUI class declare a static function named like fireLogInPropEvent. You will need to declare your LoginFrame instance as static. Then inside this function put loginFrame.firePropertyChange("buttonLogOffClicked", false, true) to listen to this property.

    public class GUI extends SingleFrameApplication implements PropertyChangeListener {
    
    
        private MainFrame mainFrame = null;
        private static LoginFrame loginFrame = new LoginFrame();
    
        /// your other code
    
        private void showLoginFrame() {
            // loginFrame = new LoginFrame(); <------- already created hence commenting out
            loginFrame.setVisible(true);
            loginFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            // Notify every change to every bound property for that object:
            loginFrame.addPropertyChangeListener(this); 
    
         }
    
          public static void fireLogInPropEvent()
          {
             loginFrame.firePropertyChange("buttonLogOffClicked", false, true);
          }
    
       }
    
Sage
  • 15,290
  • 3
  • 33
  • 38
  • mmm seems don't work, because in this class I have not a LoginFrame instance...what am I missing? – AndreaNobili Nov 18 '13 at 22:46
  • @AndreaNobili: as Sage is saying, what you're missing is that you seem to be adding your PropertyChangeListener to the *Wrong Object*. You need to add it to the correct object for the code to make sense and to work. 1+ – Hovercraft Full Of Eels Nov 18 '13 at 22:54
  • @AndreaNobili, you have actually understood that, you will need an instance of `LoginFrame` in the `MainFrame` class to fire a property change event for `LoginFrame` from `MainFrame`. This type of hazard you will face, for using multiple frame in one application. I have said you many times before, and i am telling you now, change the design style. Make use of card layout and do things with one frame – Sage Nov 19 '13 at 06:28
  • I can't change the layout style...I am workikg on an old big application I have to mantein the original layout also if it is not so smart :( – AndreaNobili Nov 19 '13 at 07:35
  • @AndreaNobili, ok. Take a look at my edited answer. you should have got it working now with changes i have mentioned – Sage Nov 19 '13 at 07:36