Thailer
Thailer

Reputation: 43

ActionListener in a separate Class

First off this is a homework assignment so explanations and pointers are preferred over flat solutions. We are learning swing and are practicing separate class ActionListeners (bonus question, why would you use a separate class over an inner class, it seems like inner class is simpler and less error prone without losing any real abilities). The problems I have been running into are passing the Frame as a parameter so that the separate class can access the tools it needs, and then using the separate class to actually change the display. The project is supposed to work something like a slideshow, having a timer as a default switch, but also implementing buttons to move manually.

import javax.swing.*;

import java.awt.BorderLayout;
import java.awt.Image;
import java.awt.event.*;
import java.io.File;

public class SliderFrame extends JFrame{

    public SliderFrame(){
        File file1 = new File("images");  //change as necessary
        File file = new File("images\\CMU");
        File[] paths;
        paths = file.listFiles();

        //file1
        ImageIcon left = new ImageIcon("backward.png");
        ImageIcon right = new ImageIcon("forward.png");

        JButton btnLeft = new JButton(left);
        btnLeft.addActionListener(new MyActionListener(this));

        JButton btnRight = new JButton(right);
        btnRight.addActionListener(new MyActionListener(this));

        JTextField jtfTitle = new JTextField("Welcome to CMU!");
        JLabel jlbMain = new JLabel();

        new Timer(2000, new MyActionListener(this)).start();

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.add("PAGE_START", jtfTitle);
        panel.add("Center", jlbMain);
        panel.add("LINE_START", btnLeft);
        panel.add("LINE_END", btnRight);

        add(panel);

        setTitle("CPS240 SlideShow");
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        pack();
        setVisible(true);

    }
    public static void main(String[] args) {
        JFrame frame = new SliderFrame();
        btnRight.addActionListener(new MyActionListener(frame));
    }

}

And then my ActionListener Class

import java.awt.event.*;

import javax.swing.*;
//does it need to extend SliderFrame?  Originally I thought it would help with some of my errors
public class MyActionListener extends SliderFrame implements ActionListener {
JFrame frame;

    public MyActionListener(JFrame frame) {
        this.frame = frame;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() instanceof Timer){
            //here's where I need to be able to change the 'main' label in the frame
        } else if(e.getSource() == btnRight){
            //trying to figure out if the left or right button was pushed
        } else{

        }
    }

}

I'm not sure if the source of my errors lie in how I set up the format to start with or if I'm just not getting something. Any help or opinions would be greatly appreciated.

Upvotes: 2

Views: 1240

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347184

bonus question, why would you use a separate class over an inner class, it seems like inner class is simpler and less error prone without losing any real abilities

Initially, you had no choice, as you couldn't have inner classes, but, there may be occasions where the functionality is common and can easily be repeated, for example, an "Open File" action, which is manged by a toolbar button, menu item and keyboard short cut...


First your ActionListener does not need to extend from SliderFrame, but instead, probably wants a reference to an instance of SliderFrame...

This

public class MyActionListener extends SliderFrame implements ActionListener {

Should probably be more like

public class MyActionListener implements ActionListener {

Instead of passing a reference of JFrame, you will want to pass a reference of SliderFrame. Having said that, I have no idea where btnRight is, but I'm pretty sure it shouldn't be maintained within the main method, but within the SliderFrame itself...

public class SliderFrame extends JFrame{
    public SliderFrame(){
        //...
        btnRight.addActionListener(new MyActionListener(this));

You ActionListener should also expect an instance of SliderFrame

public class MyActionListener extends SliderFrame implements ActionListener {
    private SliderFrame frame;

    public MyActionListener(SliderFrame frame) {

This allows your ActionListener to make use of functionality that is defined by the SliderFrame, which won't be available from an instance of JFrame

Next, you want to provide functionality in your SliderFrame which can be used to update the state of the slide show...

public class SliderFrame extends JFrame{
    //...
    public void nextSlide() {
        //...
    }

    public void previousSlide() {
        //...
    }

Then when your ActionListener is triggered, you just call the appropriate methods on SliderFrame

public class NextSlideActionListener extends SliderFrame implements ActionListener {
    //...    
    @Override
    public void actionPerformed(ActionEvent e) {
        frame.nextSlide();
    }

}

(ps- the above example can be used by the Timer and "next" button, because the functionality is the same for both)

Upvotes: 2

Related Questions