简体   繁体   中英

Using an inner class actionListener in another class

So I've made this queue using a linked list, a Job object to go inside the queue. I've made the program work just using those 2 class files but now I am trying to make it work with a GUI.

I want to be able to run my program from my GUI main method, using the Queue and Job files. The GUI I have created has 8 buttons and a JTextArea for output. I want to be able to perform each function (enqueue, display length of queue ect) by clicking the button.

my query is at the end

PS. The original main method is omitted to keep it to the point.

This is my Job object to go into the queue, general stuff here... omitted getters/setters:

public class Job 
{

String ID; //(A unique number to identify each print job)
String userID; //(The login of the user that sent the document to print)
String documentName; //(The name of the document being printed)
int fileSize; //(Size of the document being printed in Kb’s)

public Job(String p, String u, String e, int f) 
{ //local variables n,t,e only used in this method
    printID = p;
    userID = u;
    documentName = e;
            fileSize = f;
}

This is the Queue class with constructors and methods... These all work AFAIK.

public class Queue<Item> implements Iterable<Item> 
{
private int N;         // number of elements on queue
private Node first;    // beginning of queue
private Node last;     // end of queue



// helper linked list class
private class Node 
{
    private Item item;
    private Node next;
}

/**
 * Initialises an empty queue.
 */
public Queue() 
{
    first = null;
    last  = null;
    N = 0;
  //  assert check();
}

//is the list empty?
public boolean isEmpty() 
{
    return first == null;
}

//gives number of elements in the queue
public int length() 
{
    return N;     
}


 //looks at first item, if it is empty then return error. If it has something then return
 the   content of the element.
 public Item peek() 
 {
    if (isEmpty()) throw new NoSuchElementException("Nothing in queue");
    return first.item; 
 }

//add an item
 public void enqueue(Item item) 
{
    Node oldlast = last;  //move the current last to a placeholder
    last = new Node();  //create a new node inside of last
    last.item = item; //place the item i passed to the method call to the new last's item area
    last.next = null; //set the end of the queue
    if (isEmpty())   //checks the rest of the queue
        first = last;  //if empty creates a queue of 1 element length
    else           
        oldlast.next = last; //if not empty then previous last will point to this new one
    N++; //increment the number of elements being tracked.

}

 //remove an item
 public Item dequeue() 
 {
    if (isEmpty()) throw new NoSuchElementException("Nothing in queue");
    Item item = first.item;
    first = first.next;
    N--;
    if (isEmpty()) last = null;   // to avoid loitering

    return item;
}

This is my GUI:

public class GUI {   

  public static void main(String[] args) 
  {        
    Queue s = new Queue();

    JFrame frame = new JFrame("test");
    frame.setVisible(true);
    frame.setSize(500,500);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);



    JPanel panel = new JPanel(new GridBagLayout());
    frame.getContentPane().add(panel, BorderLayout.NORTH);

    GridBagConstraints c = new GridBagConstraints();

    JButton button1 = new JButton("Enqueue a print job");
    c.gridx = 0;
    c.gridy = 0;
    c.insets = new Insets(10,10,10,10);
    panel.add(button1, c);
    button1.addActionListener(new Enqueue(){});

    JButton button2 = new JButton("Dequeue a print job");
    c.gridx = 0;
    c.gridy = 1;
    panel.add(button2, c);
    button2.addActionListener(new Dequeue(){});

    JButton button3 = new JButton("is the queue empty?");
    c.gridx = 1;
    c.gridy = 0;
    panel.add(button3, c);
    button3.addActionListener(new empty(){});

    JButton button4 = new JButton("Print first in queue");
    c.gridx = 1;
    c.gridy = 1;
    panel.add(button4, c);
    button4.addActionListener(new first(){});

    JButton button5 = new JButton("Length of queue");
    c.gridx = 0;
    c.gridy = 2;
    panel.add(button5, c);
    button5.addActionListener(new length(){});

    JButton button6 = new JButton("Print entire queue");
    c.gridx = 1;
    c.gridy = 2;
    panel.add(button6, c); 
    button6.addActionListener(new printAll() {});

    JTextArea jTextArea = new JTextArea();


    c.gridx = 4;
    c.gridy = 4;
    frame.add( jTextArea, BorderLayout.SOUTH);

This is the inner class (in the GUI file) in question: What am I doing wrong here? I've tried trying to reference the 's' queue but to this separate class the queue just doesn't exist outside of the main; this means I cannot perform functions on it.

 static class length implements ActionListener
 {
 public void actionPerformed (ActionEvent e) 
    { 
         System.out.println("The length of the queue is: " + s.length() +"\n");
    }
 }

I will make more actionListeners when I know what to do with this one.

Ps. if you know how to write to JTextArea from the actionListener that I created in the main method in the GUI file, instead of using Sys out that would help me too!

This is my first attempt at using GUIs so any insight would be great. Thanks :)

You declared:

PrintQueue s = new PrintQueue();

inside the main() method - which means that it's available only from inside main() (method scope). If you want to use it outside the method, you'll have to declare it as a class member and expose it via a "get()" method.

For example:

public class GUI { 

  static PrintQueue s = null;  

  public static void main(String[] args) {        
    s = new PrintQueue();
    ...
  }

  public PrintQueue getS() {return s;}

Then you'll be able to use it:

public void actionPerformed (ActionEvent e) { 
     System.out.println("The length of the queue is: " + s.length() +"\n"); //from the same class
}

or from outside the class using:

GUI gui = new Gui();
PrintQueue s = gui.getS();

Comment :
I'm not sure if main() is the right place to instantiate PrintQueue - it might be so, but it might also be that a constructor would be a better idea.

I think the following code would be a legal example of adding an inner class ActionListener. I'm writing this outside of my IDE, and often make mistakes, so you will have to check it out in your IDE.

in declarations

   final PrintQueue s = new PrintQueue();

in constructor

   button1.addActionListener(new ActionCommand()
   {
      public void actionPerformed (ActionEvent e) 
      { 
          System.out.println("The length of the queue is: " + s.length() +"\n");
      }    

   });

Main points:

  • the new ActionCommand doesn't have a name, it is anonymous,

  • any variable referenced in an inner class must be final ,

  • the anonymous inner class is an actual class, not a method of a class,

  • the inner class should have an actionPerformed method as part of its definition.

If you need to distinguish between several different JButtons, there are two common ways to program this.

(1) add a "setActionCommand" method to the JButton and give the button an identifying string. Then all your buttons can invoke a new instance of a single class that implements ActionListener (such as your Length class), and the ActionCommand string can be derived from the ActionEvent parameter e and used to branch to the code for the corresponding button.

(2) make a separate inner class ActionListener for each button and customize the actionPerformed method for that button.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM