0

I have a instance of a custom JLabel and i want to changes its text in all frames, but the text is changing only on the last opened frame. There's a way i can achieve this?

Here's what happens: enter image description here

And my code:

App.java

package test;

import javax.swing.JFrame;

public class App extends JFrame {

    protected static App app;

    private String loggedUser;
    private MyCustomLabel myCustomLabel;

    public App() {
        loggedUser = "User One";
        myCustomLabel = new MyCustomLabel(loggedUser);
    }

    public static App getApp() {
        return app;
    }

    public MyCustomLabel getMyCustomLabel() {
        return myCustomLabel;
    }

    public String getLoggedUser() {
        return loggedUser;
    }

    public void setLoggedUser(String loggedUser) {
        this.loggedUser = loggedUser;
    }

}

FrmApp.java

package test;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

/**
 *
 * @author Marco
 */
public class FrmApp extends App {

    public FrmApp() {
        app = new App();
        initComponents();
    }

    private void initComponents() {
        setLayout(new FlowLayout());
        setSize(300, 200);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        btnFrmOne = new JButton("Open frmOne");
        btnFrmOne.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                FrmOne frmOne = new FrmOne();
                frmOne.setVisible(true);
            }
        });
        add(btnFrmOne);

        btnFrmTwo = new JButton("Open frmTwo");
        btnFrmTwo.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                FrmTwo frmTwo = new FrmTwo();
                frmTwo.setVisible(true);
            }
        });
        add(btnFrmTwo);

        btnChangeUser = new JButton("Change user");
        btnChangeUser.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (App.getApp().getLoggedUser().equals("User One")) {
                    App.getApp().setLoggedUser("User Two");
                } else {
                    App.getApp().setLoggedUser("User One");
                }

                App.getApp().getMyCustomLabel().refresh();
            }
        });
        add(btnChangeUser);
    }

    private JButton btnFrmOne;
    private JButton btnFrmTwo;
    private JButton btnChangeUser;

    public static void main(String args[]) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(FrmApp.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            Logger.getLogger(FrmApp.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(FrmApp.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedLookAndFeelException ex) {
            Logger.getLogger(FrmApp.class.getName()).log(Level.SEVERE, null, ex);
        }

        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new FrmApp().setVisible(true);
            }
        });
    }

}

FrmOne.java

package test;

import java.awt.FlowLayout;
import javax.swing.JFrame;

public class FrmOne extends JFrame {

    public FrmOne() {
        initComponents();
    }

    private void initComponents() {
        setLayout(new FlowLayout());
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setSize(150, 100);

        add(App.getApp().getMyCustomLabel());
    }

}

FrmTwo.java

package test;

import java.awt.FlowLayout;
import javax.swing.JFrame;

public class FrmTwo extends JFrame {

    public FrmTwo() {
        initComponents();
    }

    private void initComponents() {
        setLayout(new FlowLayout());
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        setSize(150, 100);

        add(App.getApp().getMyCustomLabel());
    }

}

MyCustomLabel.java

package test;

import javax.swing.JLabel;

public class MyCustomLabel extends JLabel {

    public MyCustomLabel(String loggedUser) {
        initComponents(loggedUser);
    }

    private void initComponents(String loggedUser) {
        setText(loggedUser);
    }

    public void refresh() {
        setText(App.getApp().getLoggedUser());
    }

}

Update

This is what im doing now to do what i wanted.

App.java

public class App extends JFrame {

    public App() {
        User user = new User(1, "User One");
        LoggedUser.getInstance().setUser(user);

        initComponents();
    }

    public static void main(String[] args) {
        new App().setVisible(true);
    }

    private void initComponents() {
        setSize(200, 200);
        setLocation(400, 200);
        setLayout(new FlowLayout());
        setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JButton btn1 = new JButton("dlgOne");
        btn1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                DlgOne dlgOne = new DlgOne(App.this, false);
                dlgOne.setVisible(true);
            }
        });

        JButton btn2 = new JButton("dlgTwo");
        btn2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                DlgTwo dlgTwo = new DlgTwo(App.this, false);
                dlgTwo.setVisible(true);
            }
        });

        JButton btn3 = new JButton("change user");
        btn3.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (LoggedUser.getInstance().getUser().getId() == 1) {
                    User user = new User(2, "User Two");
                    LoggedUser.getInstance().setUser(user);
                } else {
                    User user = new User(1, "User One");
                    LoggedUser.getInstance().setUser(user);
                }
            }
        });

        add(btn1);
        add(btn2);
        add(btn3);
    }
}

MyCustomPanel.java

public class MyCustomPanel extends JPanel implements Observer {

    private JLabel label;

    public MyCustomPanel() {
        initComponents();
    }

    @Override
    public void update(Observable o, Object arg) {
        //LoggedUser u = (LoggedUser) o;
        //System.out.println(u.getUser().getId());

        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                label.setText(LoggedUser.getInstance().getUser().getName());
            }

        });
    }

    private void initComponents() {
        LoggedUser.getInstance().addObserver(this);

        label = new JLabel(LoggedUser.getInstance().getUser().getName());
        add(label);
    }

}

User.java

public class User {

    private int id;
    private String name;

    public User(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

DlgOne.java

public class DlgOne extends JDialog {

    public DlgOne(Frame owner, boolean modal) {
        super(owner, modal);
        initComponents();
    }

    private void initComponents() {
        setTitle("dlgOne");
        setSize(200, 200);
        setLocation(600, 200);
        setLayout(new FlowLayout());
        setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        add(new MyCustomPanel());
    }

}

DlgTwo.java

public class DlgTwo extends JDialog {

    public DlgTwo(Frame owner, boolean modal) {
        super(owner, modal);
        initComponents();
    }

    private void initComponents() {
        setTitle("dlgTwo");
        setSize(200, 200);
        setLocation(800, 200);
        setLayout(new FlowLayout());
        setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
        add(new MyCustomPanel());
    }

}

LoggedUser.java

public class LoggedUser extends Observable {

    private static LoggedUser instance;

    public static LoggedUser getInstance() {
        if (instance == null) {
            instance = new LoggedUser();
        }

        return instance;
    }

    private User user;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
        setChanged();
        notifyObservers();
    }

}
Marco Gustavo
  • 69
  • 2
  • 10
  • You want to wire things using an observer design pattern, so when the user changes, all registered listeners (here the two windows -- which should be dialogs, not JFrames -- change). Look up M-V-C or Model-View-Controller as the best way to structure this in an over-all fashion and then re-structure program accordingly. – Hovercraft Full Of Eels Apr 04 '17 at 15:26
  • See [The Use of Multiple JFrames, Good/Bad Practice?](http://stackoverflow.com/q/9554636/418556) – Andrew Thompson Apr 04 '17 at 15:33
  • @HovercraftFullOfEels I've used the observer and now im able to do what i wanted. Btw, im updating the code. – Marco Gustavo Apr 04 '17 at 23:06
  • @AndrewThompson Thank you! – Marco Gustavo Apr 04 '17 at 23:09

1 Answers1

1

I have a instance of a custom JLabel and i want to changes its text in all frames,

A Swing component can only have a single parent. So you actually have two instances of your custom label. So updating the text in one label does not affect the other.

What you can do is create a PlainDocument to contain the text to be shared by multiple JTextFields. Then when the text is the Document is changed all the text fields will be updated.

So in the App class you would have:

private PlainDocument sharedDocument = new PlainDocument();

and you would create a method to access the Document. Maybe something like getSharedDocument().

Then in the form classes you would do something like:

//add(App.getApp().getMyCustomLabel());
JTextField textField = new JTextField( App.getApp().getSharedDocument() );
//  customize text field to look like a label
textField.setBorder( null );
textField.setEditable( false );
add( textField );
camickr
  • 321,443
  • 19
  • 166
  • 288