0

Thank you for your help. I'm a newbie trying something quite simple. I want to have a window (panel) with a text (JLabel) that changes every few seconds. The whole application is working perfectly except for the JLabel that is being updated (the text does change), but it doesn't show on the window (panel). The window keeps the same text from beginning to end even though I have checkpoints that tell me that the text of the JLabel is being updated and changing. I've looked for the same issue everywhere and have found some comments, but none helped. Someone said is the ActionListener, but when I got rid of it it didn't make a difference. Someone said the loop in the thread doesn't let the JLabel refresh so I tried having the JLabel and it's update being on a separate thread and that didn't work either. The only thing I haven't tried is using a swingWorker (don't quite know how). The thread attempt was with a thread class with a runnable method. Again, that way everything worked perfectly, except that the JLabel didn't repaint itself.

Here's is the code without the thread. It's all in one class.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.*;





public class SWUI extends JFrame implements ActionListener {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private JPanel panel;
    JLabel label;
    private Font font;


    //Set up the interface. SWUI is working perfectly
SWUI() {

        System.out.println("run started");      //just to check that the method gets called.
        panel = new JPanel();
        panel.setLayout(new BorderLayout(1, 1));
        panel.setPreferredSize(new Dimension(1000, 400));
        panel.setBackground(Color.white);
        getContentPane().add(panel);

        label = new JLabel("Ready");                    //These four statements are working
        label.setHorizontalAlignment(JLabel.CENTER);
        font = new Font("Comic Sans MS", Font.PLAIN, 70);
        label.setFont(font);

        panel.add(label, BorderLayout.CENTER);

        System.out.println("run done and draw to start");

        label.setText("label is updatable");        //Checks that the whole method gets done and that the label is indeed able to get updated. It works.

    }


// draw() mostly sets the Frame up, names it, sets closing behavior. It's working.
    public void draw() {

        System.out.println("draw started");         //To check that the method is getting invoked.

        SWUI frame = new SWUI();
        frame.setTitle("Sight Words Rock");

        WindowListener l = new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
           System.exit(0);
         }
      };
        frame.addWindowListener(l);

        frame.pack();
        frame.setVisible(true);

        System.out.println("draw done");        //To check that the whole method went through. It's all working.

    }



    //Should change the label to 4 sentences every 1 second. The text of the label does change, but it doesn't show on the interface (panel).
    private void updateLabel(String word){

        label.setText(word);

        //label.revalidate();       //I tried these three statements one at a time and both together and they made no difference.
        //label.updateUI();
        //label.repaint();

        System.out.println("The label now is: "+ label.getText());   //This confirms that the setText() is indeed changing the text
                                                                    // of the label, but it doesn't show on the interface.
    }


    //Main gets the draw() started to initiate the interface and gets the sentences changed and sent to updateLabel() every second.
    public static void main(String args[]) 

        throws InterruptedException {

        SWUI ui = new SWUI();
        ui.draw();


        String importantInfo[] = {
            "Mares eat oats",
            "Dogs eat oats",
            "Little lambs eat ivy",
            "A kid will eat ivy too"
        };

        for (int i = 0;
             i < importantInfo.length;
             i++) {
            //Pause for 1 second
            Thread.sleep(1000);

            //Print a message
            System.out.println(importantInfo[i]);

            ui.label.setText(importantInfo[i]);
            ui.updateLabel(importantInfo[i]);
        }

    }

    //This will come later once I figure how to fix the label. Someone else suggested that the problem were the listeners not letting the thread
    // do the repainting(), but I tried getting rid of the "implements ActionListener" and the actionPerformed methods and it didn't make a
    // difference. It still didn't work.
    @Override
    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub

    }
}
Sarfaraz Khan
  • 2,166
  • 2
  • 14
  • 29
  • So which thread are you calling `setText` from? Remember that all updates to swing components must be made on the EDT, use `SwingUtilities.invokeLater` if you need to trigger the update from another thread. – Ian Roberts Jul 12 '15 at 17:02
  • 1) Use a logical and consistent form of indenting code lines and blocks. The indentation is intended to make the flow of the code easier to follow! 2) A single blank line of white space in source code is all that is *ever* needed. Blank lines after `{` or before `}` are also typically redundant. – Andrew Thompson Jul 12 '15 at 19:06

1 Answers1

0

Your draw method in SWUI creates an entirely new frame while your updates go to the initial frame which is never really set visible. To fix, your draw method should look more like this.

public void draw() {

        System.out.println("draw started");         //To check that the method is getting invoked.

        setTitle("Sight Words Rock");

        WindowListener l = new WindowAdapter() {
         public void windowClosing(WindowEvent e) {
           System.exit(0);
         }
      };
        addWindowListener(l);

        pack();
        setVisible(true);
    System.out.println("draw done");        //To check that the whole method went through. It's all working.

}
pvg
  • 2,673
  • 4
  • 17
  • 31
  • Thank you so much pvg for a thorough and clear explanation. It worked perfectly. – Nico Olivares Jul 12 '15 at 20:06
  • System.exit(0); in windowClosing == JFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE) – mKorbel Jul 12 '15 at 21:50
  • Feel free to add an edit @mKorbel. I didn't really mess with it much, the indentation is poop, it's probably best not to subclass JFrame to begin with, lots of ways it can be better. – pvg Jul 12 '15 at 21:53