2

Pure beginner question here. I'm modifying a code and am now stuck on the following questions;

My timer is called in the upper class. But my int count is being called in the class below.

Whenever i add an if statement like;

if (count == 2) { t.stop();}

i get errors because the int is in the class below and the t (timer) in the class above.

  1. How can i add an if statement when there are two classes involved?

  2. And if i want to add a new actionlistener for a button to stop the count, do i put this in the class above or under?

Code here

Thanks in advance

Opoe
  • 1,337
  • 8
  • 30
  • 56

2 Answers2

8

Because ClockListener is a nested class (lower), the enclosing instance (upper) can access the listener's private fields. If you have a reference to an instance of ClockListener,

ClockListener cl = new ClockListener();

you can use it to initialize your timer

Timer t = new Timer(1000, cl);

and you can use it in your test:

if (cl.count == 2) { t.stop(); }

Addendum: For reference, here's a variation of your program that uses a JToggleButton to control the timer. As suggested earlier, you had used Calendar to minimize Timer drift. Like you, I abandoned the approach as irrelevant in a low-resolution application.

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.Timer;

/** @see https://stackoverflow.com/questions/5528939*/
class ClockExample extends JFrame {

    private static final int N = 60;
    private static final String stop = "Stop";
    private static final String start = "Start";
    private final ClockListener cl = new ClockListener();
    private final Timer t = new Timer(1000, cl);
    private final JTextField tf = new JTextField(3);

    public ClockExample() {
        t.setInitialDelay(0);

        JPanel panel = new JPanel();
        tf.setHorizontalAlignment(JTextField.RIGHT);
        tf.setEditable(false);
        panel.add(tf);
        final JToggleButton b = new JToggleButton(stop);
        b.addItemListener(new ItemListener() {

            @Override
            public void itemStateChanged(ItemEvent e) {
                if (b.isSelected()) {
                    t.stop();
                    b.setText(start);
                } else {
                    t.start();
                    b.setText(stop);
                }
            }
        });
        panel.add(b);

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.add(panel);
        this.setTitle("Timer");
        this.pack();
        this.setLocationRelativeTo(null);
        this.setVisible(true);
    }

    public void start() {
        t.start();
    }

    private class ClockListener implements ActionListener {

        private int count;

        @Override
        public void actionPerformed(ActionEvent e) {
            count %= N;
            tf.setText(String.valueOf(count));
            count++;
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                ClockExample clock = new ClockExample();
                clock.start();
            }
        });
    }
}
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • For reference, I have included your terms, `lower` and `upper`, but the [correct](http://download.oracle.com/javase/tutorial/java/javaOO/nested.html) terms are `inner` (for your non-static, nested `ClockListener`) and `enclosing` (for your outer `JFrame`). – trashgod Apr 03 '11 at 10:49
  • Not at all; the terminology can be obscure. I've added a link to the tutorial. – trashgod Apr 03 '11 at 11:09
  • but do i still need this line then? javax.swing.Timer t = new javax.swing.Timer(1000, new ClockListener()); t.start(); – Opoe Apr 03 '11 at 11:14
  • Yes, if you want to invoke any methods of `t`; but use `Timer t = new Timer(1000, cl)`, or you'll have two instances of the `ClockListener`, only one of which will have a changing `count`. – trashgod Apr 03 '11 at 11:21
  • yes because now the error says, timer t is already being called – Opoe Apr 03 '11 at 11:28
  • @trashgod thank you for your help, I had to use my fakeSecond for the if statement! here is the working example. http://pastebin.com/frDES3Rz Thanks! – Opoe Apr 03 '11 at 17:54
  • Excellent! Thank you for the follow-up. I added a variation above. – trashgod Apr 03 '11 at 18:46
  • @trashgod Cool, nice variation! Thank you for your help appreciate it – Opoe Apr 04 '11 at 19:52
1

Its scope resolution. Make the t public(not advisable) or make another timer in the second class which you will pass through the constructer of the second class when you invoke it. It will reference the original timer.

TrawlPhaze
  • 11
  • 2