Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / GUI / May 2006

Tip: Looking for answers? Try searching our database.

How to use actionListers within static methods

Thread view: 
Ian Wilson - 12 May 2006 16:11 GMT
In the code below I am attempting to define an ActionListener for a
button so I can do something useful when the button is pressed.

At the statement
    ButtonListener buttonListener = new ButtonListener();
Eclipse says "No enclosing instance of type Hats is accessible, Must
qualify the allocation with an enclosing instance of type Hats (e.g.
x.new A() where x is an instance of Hats".

The trouble is I never intend to instantiate Hats since I don't ever
expect to need multiple Hats objects in existence at the same time.

Q.1 Is there a fix?

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

import javax.swing.*;

public class StaticGUI {
  public static JFrame frame = new JFrame();
  public static void main(String[] args) {
    // main GUI with menu that invokes ...
    Hats.editHats();
  }
}

class Hats {
  // so can refer to addButton in buttonListener:
  public static JButton addButton;

  public static void editHats() {
    addButton = new JButton("Add");
    JButton editButton = new JButton("Edit");
    JButton removeButton = new JButton("Remove");
    ButtonListener buttonListener = new ButtonListener();
    addButton.addActionListener(buttonListener);
    editButton.addActionListener(buttonListener);
    removeButton.addActionListener(buttonListener);
    JPanel buttonPanel = new JPanel();
    buttonPanel.add(addButton);
    buttonPanel.add(editButton);
    buttonPanel.add(removeButton);
    JPanel panel = new JPanel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
    JTextArea textArea = new JTextArea();
    panel.add(textArea);
    panel.add(buttonPanel);
    JOptionPane pane = new JOptionPane(
        panel,              // "message"
        JOptionPane.PLAIN_MESSAGE,    // messagetype
        JOptionPane.OK_CANCEL_OPTION  // optiontype
    );
    JDialog dialog = pane.createDialog(StaticGUI.frame,"Test");
    dialog.setResizable(true);
    dialog.setVisible(true);
  } // method editHats

  // an inner class within Hats, to listen to Hat-related button events
  class ButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      JComponent c = (JComponent) e.getSource();
      if (c == addButton) {
        System.out.println ("You pressed 'Add'");
      }
    }
  }
} // class Hats

Q.2 should I rethink my whole approach to my design of this application?
Vova Reznik - 12 May 2006 16:41 GMT
> In the code below I am attempting to define an ActionListener for a
> button so I can do something useful when the button is pressed.
[quoted text clipped - 9 lines]
>
> Q.1 Is there a fix?

Yes, define class Hats as static

> import java.awt.event.ActionEvent;
> import java.awt.event.ActionListener;
[quoted text clipped - 52 lines]
>
> Q.2 should I rethink my whole approach to my design of this application?

Yes, put Hats into another .java file
Thomas Fritsch - 12 May 2006 17:17 GMT
>> At the statement
>>     ButtonListener buttonListener = new ButtonListener();
[quoted text clipped - 5 lines]
>
> Yes, define class Hats as static
You probably meant:
  Yes, define class ButtonListener as static

>> class Hats {
>>   // so can refer to addButton in buttonListener:
[quoted text clipped - 5 lines]
>>     JButton removeButton = new JButton("Remove");
>>     ButtonListener buttonListener = new ButtonListener();
[...]
>>   } // method editHats
>>
>>   // an inner class within Hats, to listen to Hat-related button events
>>   class ButtonListener implements ActionListener {
static class ButtonListener implements ActionListener {
>>     public void actionPerformed(ActionEvent e) {
>>       JComponent c = (JComponent) e.getSource();
[quoted text clipped - 4 lines]
>>   }
>> } // class Hats

Signature

"Thomas:Fritsch$ops:de".replace(':','.').replace('$','@')

Ian Wilson - 12 May 2006 17:23 GMT
>> In the code below I am attempting to define an ActionListener for a
>> button so I can do something useful when the button is pressed.
[quoted text clipped - 11 lines]
>
> Yes, define class Hats as static

Thanks, I changed
  class Hats {
to
  static class Hats

Eclipse says "Illegal modifier for the class Hats, only public, abstract
& final are permitted"

<snip: code>

>> Q.2 should I rethink my whole approach to my design of this application?
>
> Yes, put Hats into another .java file

Thanks, I did that too, I get the same error messages as before.

Warning: long rambling question ahead, skip the remainder of this
posting if you dislike long rambling questions.

In my real application I do have classes in separate files. I put them
together in my example to make it easier for others to cut, paste and
compile.

What I had in mind when I wrote Q2 was more general. My app has a main
JFrame with a JMenubar from which the user can select various
transactions. Some of these maintain reference data, i.e. relatively
static lists of things which are stored in a database.

Take, for example, a list of ISO country codes. I did wonder whether my
main() should instantiate an instance of CountryList (say) at the start
and then invoke instance methods in response to menu selections.

Since I'd never need more than one instance of CountryList this seemed a
bit of overkill, I'd have to instantiate one of each type of reference
data at the program startup or keep track of whether I'd instantiated
each of them before. Maybe I could instantiate one object as needed,
just to act as a reference for method calls.

It seemed simpler (my procedural programming roots may be showing) to
use a class simply to group together a bunch of static methods relating
to a specific type of reference data (e.g. class CountryList contains
all the things you can do with the DB table of countries: view a list of
them, add a country to the list, retrieve attributes of a specific
country, ...)

However I keep bumping up against issues. E.g. ActionListener
documentation examples are often along the lines of
  component.addActionListener(this)
where "this" isn't usable in a class method.
This kind of mismatch makes me wonder if my fundamental approach is
ill-chosen.
Vova Reznik - 12 May 2006 17:33 GMT
I'm sorry for previous response
you need to define ButtonListener
as static

> In the code below I am attempting to define an ActionListener for a
> button so I can do something useful when the button is pressed.
[quoted text clipped - 66 lines]
>
> Q.2 should I rethink my whole approach to my design of this application?
Fred Kleinschmidt - 12 May 2006 19:40 GMT
> In the code below I am attempting to define an ActionListener for a button
> so I can do something useful when the button is pressed.
[quoted text clipped - 66 lines]
>
> Q.2 should I rethink my whole approach to my design of this application?

You should rethink your approach.
You make all Hats methods static because you never intend to instantiate
Hats since don't  expect to need multiple Hats objects in existence at the
same time.
First, if it is static, you never have even one object...
Second, that's not really a good reason to make the class static.

But Hats does instantiate a JDialog, so why not just make Hats
the JDialog itself? And have it implement ActionListener, so you
don't have to have inner classes:

public class Hats extends JDialog implements ActionListener {
 // constructor
 public Hats() {
   // Create buttons, panels, etc.
   ...
   // set up ActionListener
   addButton.addActionListener( this );
   editButton.addActionListener( this );
   removeButton.addActionListener( this );
 }

 // ActionListener method
 public void actionPerformed( ActionEvent e ) {
   // body here
 }
}
Ian Wilson - 15 May 2006 10:22 GMT
>>In the code below I am attempting to define an ActionListener for a button
>>so I can do something useful when the button is pressed.
[quoted text clipped - 94 lines]
>   }
> }

Thanks Fred, Thomas & Vova. I've made ButtonListener static and will
make an attempt at a non-static approach for comparison.
Fred.Swartz@gmail.com - 22 May 2006 20:58 GMT
To stay in the mainstream of GUI building, don't go down the static
path.  Use the common approach of subclassing JFrame, building the GUI
in its constructor, and define main in the same class.  Main should
just create an object of that class, then setVisible(true) on it.  Or
do that after starting a separate thread if the GUI is complicated
enough to require that.

There's no advantage to the static approach -- basically the same
amount of memory has to be allocated anyway.  Java revolves around
objects, and the big disadvantage of the static approach is that not
even one object is allocated for your class.  Perhaps the static
approach works for everything, but you'll discover that you have to do
a number of things a little differently.

You want a JFrame subclass to get one object, not multiple objects.
This will also keep you in the mainstream with more useful examples.
Ian Wilson - 25 May 2006 10:08 GMT
> To stay in the mainstream of GUI building, don't go down the static
> path.  Use the common approach of subclassing JFrame, building the GUI
[quoted text clipped - 12 lines]
> You want a JFrame subclass to get one object, not multiple objects.
> This will also keep you in the mainstream with more useful examples.

I'm having a problem with this approach. When I construct a JOptionPane,
I don't know how to specify the parent frame correctly. In the example
below, on WinXP, if you open the MyApp5 Customer dialog, then open
another app over the top, then click MyApp5 in the tray at the bottom to
bring it to front, you don't see the modal dialog because I havent set
its parent correctly. How do I specify the parent?

/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class MyApp5 extends JFrame implements ActionListener {
    private static final long serialVersionUID = 3258412832977860659L;

    public MyApp5() {
        JMenu editMenu = new JMenu("Edit");
        editMenu.add(makeMenuItem("Suppliers"));
        editMenu.add(makeMenuItem("Customers"));
        JMenuBar menuBar = new JMenuBar();
        menuBar.add(editMenu);
        setJMenuBar(menuBar);
    }

    JMenuItem makeMenuItem(String itemName) {
        JMenuItem item = new JMenuItem(itemName);
        item.addActionListener(this);
        return item;
    }

    public void actionPerformed(ActionEvent e) {
        String command = e.getActionCommand();
        if (command == "Customers") {
            MyApp5CustomerPane custPane = new MyApp5CustomerPane();
        }
        if (command == "Suppliers") {
            //
        }
        // Lots more like this
    }

    private static void createAndShowGUI() {
        JFrame frame = new MyApp5();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        int width = 600;
        int height = 400;
        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        int x = (screen.width - width) / 2;
        int y = (screen.height - height) / 2;
        frame.setBounds(x, y, width, height);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
} // class MyApp5
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

public class MyApp5CustomerPane extends JOptionPane {
    private static final long serialVersionUID = 3257571685141197368L;

    private String[] columnNames = { "Name", "City" };

    private Object[][] data = { { "British", "London" },
            { "Continental", "Houston" }, { "SouthWest", "Dallas" },
            { "United", "Chicago" }, { "Virgin", "London" } };

    public MyApp5CustomerPane() {

        JTable table = new JTable(data, columnNames);
        JScrollPane scroller = new JScrollPane(table);
        JPanel panel = new JPanel();
        panel.add(scroller);
        setMessage(panel);

        setMessageType(JOptionPane.PLAIN_MESSAGE);
        setOptionType(JOptionPane.OK_CANCEL_OPTION);

        JDialog dialog = createDialog(new JFrame(), "Customers");
                                     // ^^^^^^^^ problem!
        dialog.setResizable(true);
        dialog.setVisible(true);
    }
}
/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
Ian Wilson - 26 May 2006 11:51 GMT
>> To stay in the mainstream of GUI building, don't go down the static
>> path.  Use the common approach of subclassing JFrame, building the GUI
>> in its constructor, and define main in the same class.  Main should
>> just create an object of that class, then setVisible(true) on it.  Or
>> do that after starting a separate thread if the GUI is complicated
>> enough to require that.

<snippage>

> I'm having a problem with this approach. When I construct a JOptionPane,
> I don't know how to specify the parent frame correctly. In the example
> below, on WinXP, if you open the MyApp5 Customer dialog, then open
> another app over the top, then click MyApp5 in the tray at the bottom to
> bring it to front, you don't see the modal dialog because I havent set
> its parent correctly. How do I specify the parent?

<snip: code listings>

I changed
   MyApp5CustomerPane custPane = new MyApp5CustomerPane();
   MyApp5CustomerPane custPane = new MyApp5CustomerPane(this);
...
   public MyApp5CustomerPane() {
   public MyApp5CustomerPane(JFrame parent) {
...
   JDialog dialog = createDialog(new JFrame(), "Customers");
   JDialog dialog = createDialog(parent, "Customers");

Then all was OK.


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.