Question

I am making a chat client, but I am having some problems with the code not running.

public static void login(String userName, String password) throws XMPPException {

    ConnectionConfiguration config = new ConnectionConfiguration("chat.facebook.com",5222,"Work");
    connection = new XMPPConnection(config);

    try{
        connection.connect();
        connection.login(userName, password);
        System.out.println("Login Successful");
        //gui.removeAll();

        URL temp = start.class.getResource("slate.png");

        gui.window.remove(gui.password);
        gui.window.remove(gui.username);
        gui.window.remove(gui.login);
        gui.window.remove(gui.failed);
        gui.window.setContentPane(new JLabel(new ImageIcon(temp)));
        gui.window.setBackground(new Color(27,27,27));

        System.out.println("Reached 1");
        //displayBuddyList();
        gui.list2.setVisible(true);
        System.out.println("Reached 2");
        gui.list2.setText("text test");
        System.out.println("Reached 3");

    }
    catch(Exception e){
        gui.failed.setVisible(true);
    }


}

the lines "gui.list2.setVisible(true)" and "gui.list2.setText("TestText")" seam to be not working. But I get all the System.out.println Messages.

"list2" is a JTextArea, its been adready added the JFrame I been using: Heres the code in my gui class:

window.add(list2);
list2.setBounds(0,0,window.getWidth(),window.getHeight());
list2.setVisible(false);

For all the code for further investigation: http://pastebin.com/PcSPzgBN

Was it helpful?

Solution

Your source code is long enough that it's hard to pinpoint exactly where the problem you've cited is. I think it might be exactly this line:

gui.window.setContentPane(new JLabel(new ImageIcon(temp))); // <- this line
gui.window.setBackground(new Color(27,27,27));

...
gui.list2.setText("text test");
...
gui.list2.setVisible(true);

Where after setting the content pane, list2 is probably not in the frame anymore. It's probably on whatever was the content pane before (gui.firstscreen?).

There are, however, some more general problems.

I see a pattern that looks like this:

SomeJComponent aComp1 = new SomeJComponent();

somewhere.add(aComp1);
aComp1.setBounds(/* ... */);
aComp1.setVisible(false);

SomeJComponent aComp2 = new SomeJComponent();

somewhere.add(aComp2);
aComp2.setBounds(/* ... */);
aComp2.setVisible(false);

Basically it looks like you are doing this to switch out the visible components on a frame dynamically sometimes. Your components are all overlapping and you pick which ones to be visible to reconfigure the frame. I would strongly recommend against doing this.

The "correct" way to swap the view of a container is to have separate panels and set the content pane (or even better use JComponents intended for this such as JTabbedPane). The following is a short working example that does just that:

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

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import java.awt.BorderLayout;

public class PanelSwap {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new PanelSwap().frame.setVisible(true);
            }
        });
    }

    JFrame frame;
    JPanel panel1;
    JPanel panel2;

    PanelSwap() {

        frame = new JFrame();
        frame.setLocationRelativeTo(null);

        panel1 = new JPanel(new BorderLayout());

        JButton toPanel2 = new JButton("Goto Panel 2");
        toPanel2.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                frame.setContentPane(panel2);
                frame.validate();
            }
        });

        panel1.add(toPanel2, BorderLayout.CENTER);

        panel2 = new JPanel(new BorderLayout());

        JButton toPanel1 = new JButton("Goto Panel 1");
        toPanel1.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                frame.setContentPane(panel1);
                frame.validate();
            }
        });

        panel2.add(toPanel1, BorderLayout.CENTER);

        frame.setContentPane(panel1);
        frame.pack();
    }
}

If you want some GUI elements to be shared, you can instead set the content pane to a panel with the shared elements and add/remove elements to/from that panel. Use something like BorderLayout for the best results.

The other point is that you need to be interacting with the GUI on the Event Dispatch Thread. See Concurrency in Swing for the tutorial. Specifically "Initial Threads" and "The Event Dispatch Thread".

That is what invokeLater is for. It is OK to update the GUI inside events (methods like actionPerformed) because they are executed on the EDT. Anywhere else you should use invokeLater. There are a few exceptions to the rule but for the most part you need to be doing Swing stuff on the EDT.

A last and more like an aside is you should really follow Java code conventions for names, specifically classes start with an uppercase letter. Your start and gui classes should be Start and GUI. It's further confusing because your gui class has a method called start.

OTHER TIPS

Try repainting and (re)validating the gui container (window), or the JTextArea component, after setting the component to visible.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top