Java/Event/General Event

Материал из Java эксперт
Перейти к: навигация, поиск

Event Listener List

   <source lang="java">
   

/**

* The utillib library.
* More information is available at http://www.jinchess.ru/.
* Copyright (C) 2002 Alexander Maryanovsky.
* All rights reserved.
*
* The utillib library is free software; you can redistribute
* it and/or modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The utillib library is distributed in the hope that it will
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with utillib library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

import java.util.EventListener; import java.lang.reflect.Array;

/**

* A convenient storage place for Listeners. The listeners are stored in the
* same manner as in javax.swing.event.EventListenerList.
* Note: This class is not thread safe.
*/

public class EventListenerList{

 /**
  * The array where we keep the listeners and their types.
  */
 private Object [] listenerList = new Object[0];
 /**
  * Adds the given listener as a listener of the given type.
  */
 public void add(Class listenerType, EventListener listener){
   if (listener==null)
     return;
   if (!listenerType.isInstance(listener))
     throw new IllegalArgumentException("The listener is not an instance of the listener class.");
   Object [] tempArr = new Object[listenerList.length+2];
   System.arraycopy(listenerList,0,tempArr,0,listenerList.length);
   tempArr[tempArr.length-2] = listenerType;
   tempArr[tempArr.length-1] = listener;
   listenerList = tempArr;
 }


 /**
  * Removes the given listener as a listener of the specified type.
  */
 public void remove(Class listenerType, EventListener listener){
   if (listener == null)
     return;
   if (!listenerType.isInstance(listener))
     throw new IllegalArgumentException("The listener is not an instance of the listener class.");
   for (int i=0;i<listenerList.length;i+=2){
     if ((listenerList[i]==listenerType)&&(listenerList[i+1].equals(listener))){
       Object [] tempArr = new Object[listenerList.length-2];
       System.arraycopy(listenerList,0,tempArr,0,i);
       System.arraycopy(listenerList,i+2,tempArr,i,listenerList.length-i-2);
       listenerList = tempArr;
       return;
     }
   }
 }
 /**
  * Returns the total number of listeners for this listener list.
  */
 public int getListenerCount(){
   return listenerList.length;
 }
 /**
  * Returns the amount of listeners of the specified type in this listener
  * list.
  */
 public int getListenerCount(Class listenerType){
   int count = 0;
   for (int i=0;i<listenerList.length;i+=2){
     if (listenerList[i]==listenerType)
       count++;
   }
   return count;
 }
 /**
  * Returns an array containing all the listeners in this listener list. The
  * array contains listeners and their types in the following format: the
  * element at index 2*N is the type of the listener at index 2*N+1
  * WARNING!!! Absolutely NO modification of the data contained in this array
  * should be made -- if any such manipulation is necessary, it should be done on a
  * copy of the array returned rather than the array itself.
  */
 public Object [] getListenerList(){
   return listenerList;
 }
 /**
  * Returns an array of listeners registered as the listeners of the given
  * type. Note that the returned array is an array of the actual given type
  * so it can be safely casted to that type once instead of casting each of the
  * listener.
  */
 public EventListener [] getListeners(Class listenerType){
   EventListener [] listeners = (EventListener [])Array.newInstance(listenerType,getListenerCount(listenerType));
   int count = 0;
   for (int i=0;i<listenerList.length;i+=2){
     if (listenerType==listenerList[i])
       listeners[count++] = (EventListener)listenerList[i+1];
   }
   return listeners;
 }

}



 </source>
   
  
 
  



EventTest Pane

   <source lang="java">
  

/*

* Copyright (c) 2000 David Flanagan.  All rights reserved.
* This code is from the book Java Examples in a Nutshell, 2nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book (recommended),
* visit http://www.davidflanagan.ru/javaexamples2.
*/

import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Graphics; import java.awt.event.ruponentEvent; import java.awt.event.FocusEvent; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Vector; import javax.swing.JFrame; import javax.swing.JPanel; /** A program that displays all the event that occur in its window */ public class EventTestPane extends JPanel {

 /** The constructor: register the event types we are interested in */
 public EventTestPane() {
   // We"re interested in all types of events
   this.enableEvents(AWTEvent.MOUSE_EVENT_MASK
       | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.KEY_EVENT_MASK
       | AWTEvent.FOCUS_EVENT_MASK | AWTEvent.ruPONENT_EVENT_MASK
       | AWTEvent.WINDOW_EVENT_MASK);
   this.setPreferredSize(new Dimension(500, 400));
 }
 /**
  * Display mouse events that don"t involve mouse motion. The mousemods()
  * method prints modifiers, and is defined below. The other methods return
  * additional information about the mouse event. showLine() displays a line
  * of text in the window. It is defined at the end of this class, along with
  * the paintComponent() method.
  */
 public void processMouseEvent(MouseEvent e) {
   String type = null;
   switch (e.getID()) {
   case MouseEvent.MOUSE_PRESSED:
     type = "MOUSE_PRESSED";
     break;
   case MouseEvent.MOUSE_RELEASED:
     type = "MOUSE_RELEASED";
     break;
   case MouseEvent.MOUSE_CLICKED:
     type = "MOUSE_CLICKED";
     break;
   case MouseEvent.MOUSE_ENTERED:
     type = "MOUSE_ENTERED";
     break;
   case MouseEvent.MOUSE_EXITED:
     type = "MOUSE_EXITED";
     break;
   }
   showLine(mousemods(e) + type + ": [" + e.getX() + "," + e.getY() + "] "
       + "num clicks = " + e.getClickCount()
       + (e.isPopupTrigger() ? "; is popup trigger" : ""));
   // When the mouse enters the component, request keyboard focus so
   // we can receive and respond to keyboard events
   if (e.getID() == MouseEvent.MOUSE_ENTERED)
     requestFocus();
 }
 /**
  * Display mouse moved and dragged mouse event. Note that MouseEvent is the
  * only event type that has two methods, two EventListener interfaces and
  * two adapter classes to handle two distinct categories of events. Also, as
  * seen in init(), mouse motion events must be requested separately from
  * other mouse event types.
  */
 public void processMouseMotionEvent(MouseEvent e) {
   String type = null;
   switch (e.getID()) {
   case MouseEvent.MOUSE_MOVED:
     type = "MOUSE_MOVED";
     break;
   case MouseEvent.MOUSE_DRAGGED:
     type = "MOUSE_DRAGGED";
     break;
   }
   showLine(mousemods(e) + type + ": [" + e.getX() + "," + e.getY() + "] "
       + "num clicks = " + e.getClickCount()
       + (e.isPopupTrigger() ? "; is popup trigger" : ""));
 }
 /**
  * Return a string representation of the modifiers for a MouseEvent. Note
  * that the methods called here are inherited from InputEvent.
  */
 protected String mousemods(MouseEvent e) {
   int mods = e.getModifiers();
   String s = "";
   if (e.isShiftDown())
     s += "Shift ";
   if (e.isControlDown())
     s += "Ctrl ";
   if ((mods & InputEvent.BUTTON1_MASK) != 0)
     s += "Button 1 ";
   if ((mods & InputEvent.BUTTON2_MASK) != 0)
     s += "Button 2 ";
   if ((mods & InputEvent.BUTTON3_MASK) != 0)
     s += "Button 3 ";
   return s;
 }
 /**
  * Display keyboard events.
  * 
  * Note that there are three distinct types of key events, and that key
  * events are reported by key code and/or Unicode character. KEY_PRESSED and
  * KEY_RELEASED events are generated for all key strokes. KEY_TYPED events
  * are only generated when a key stroke produces a Unicode character; these
  * events do not report a key code. If isActionKey() returns true, then the
  * key event reports only a key code, because the key that was pressed or
  * released (such as a function key) has no corresponding Unicode character.
  * Key codes can be interpreted by using the many VK_ constants defined by
  * the KeyEvent class, or they can be converted to strings using the static
  * getKeyText() method as we do here.
  */
 public void processKeyEvent(KeyEvent e) {
   String eventtype, modifiers, code, character;
   switch (e.getID()) {
   case KeyEvent.KEY_PRESSED:
     eventtype = "KEY_PRESSED";
     break;
   case KeyEvent.KEY_RELEASED:
     eventtype = "KEY_RELEASED";
     break;
   case KeyEvent.KEY_TYPED:
     eventtype = "KEY_TYPED";
     break;
   default:
     eventtype = "UNKNOWN";
   }
   // Convert the list of modifier keys to a string
   modifiers = KeyEvent.getKeyModifiersText(e.getModifiers());
   // Get string and numeric versions of the key code, if any.
   if (e.getID() == KeyEvent.KEY_TYPED)
     code = "";
   else
     code = "Code=" + KeyEvent.getKeyText(e.getKeyCode()) + " ("
         + e.getKeyCode() + ")";
   // Get string and numeric versions of the Unicode character, if any.
   if (e.isActionKey())
     character = "";
   else
     character = "Character=" + e.getKeyChar() + " (Unicode="
         + ((int) e.getKeyChar()) + ")";
   // Display it all.
   showLine(eventtype + ": " + modifiers + " " + code + " " + character);
 }
 /**
  * Display keyboard focus events. Focus can be permanently gained or lost,
  * or temporarily transferred to or from a component.
  */
 public void processFocusEvent(FocusEvent e) {
   if (e.getID() == FocusEvent.FOCUS_GAINED)
     showLine("FOCUS_GAINED" + (e.isTemporary() ? " (temporary)" : ""));
   else
     showLine("FOCUS_LOST" + (e.isTemporary() ? " (temporary)" : ""));
 }
 /** Display Component events. */
 public void processComponentEvent(ComponentEvent e) {
   switch (e.getID()) {
   case ComponentEvent.ruPONENT_MOVED:
     showLine("COMPONENT_MOVED");
     break;
   case ComponentEvent.ruPONENT_RESIZED:
     showLine("COMPONENT_RESIZED");
     break;
   case ComponentEvent.ruPONENT_HIDDEN:
     showLine("COMPONENT_HIDDEN");
     break;
   case ComponentEvent.ruPONENT_SHOWN:
     showLine("COMPONENT_SHOWN");
     break;
   }
 }
 /** Display Window events. Note the special handling of WINDOW_CLOSING */
 public void processWindowEvent(WindowEvent e) {
   switch (e.getID()) {
   case WindowEvent.WINDOW_OPENED:
     showLine("WINDOW_OPENED");
     break;
   case WindowEvent.WINDOW_CLOSED:
     showLine("WINDOW_CLOSED");
     break;
   case WindowEvent.WINDOW_CLOSING:
     showLine("WINDOW_CLOSING");
     break;
   case WindowEvent.WINDOW_ICONIFIED:
     showLine("WINDOW_ICONIFIED");
     break;
   case WindowEvent.WINDOW_DEICONIFIED:
     showLine("WINDOW_DEICONIFIED");
     break;
   case WindowEvent.WINDOW_ACTIVATED:
     showLine("WINDOW_ACTIVATED");
     break;
   case WindowEvent.WINDOW_DEACTIVATED:
     showLine("WINDOW_DEACTIVATED");
     break;
   }
   // If the user requested a window close, quit the program.
   // But first display a message, force it to be visible, and make
   // sure the user has time to read it.
   if (e.getID() == WindowEvent.WINDOW_CLOSING) {
     showLine("WINDOW_CLOSING event received.");
     showLine("Application will exit in 5 seconds");
     // Force the updates to appear now.
     update(this.getGraphics());
     // Wait five seconds
     try {
       Thread.sleep(5000);
     } catch (InterruptedException ie) {
       ;
     }
     // Exit now
     System.exit(0);
   }
 }
 /** The list of lines to display in the window */
 protected Vector lines = new Vector();
 /** Add a new line to the list of lines, and request redisplay */
 protected void showLine(String s) {
   if (lines.size() == 20)
     lines.removeElementAt(0);
   lines.addElement(s);
   repaint();
 }
 /** This method repaints the text in the window */
 public void paintComponent(Graphics g) {
   for (int i = 0; i < lines.size(); i++)
     g.drawString((String) lines.elementAt(i), 20, i * 16 + 50);
 }
 public boolean isOpaque() {
   return false;
 }
 public static void main(String[] args) {
   JFrame frame = new JFrame();
   frame.addWindowListener(new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       System.exit(0);
     }
   });
   frame.getContentPane().add(new EventTestPane(), BorderLayout.CENTER);
   // Finally, set the size of the main window, and pop it up.
   frame.setSize(600, 400);
   frame.setVisible(true);
 }

}



 </source>
   
  
 
  



KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner()

   <source lang="java">
  

import java.awt.KeyboardFocusManager; public class Main {

 public static void main(String[] argv) throws Exception {
   KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner();
 }

}


 </source>
   
  
 
  



Monitors the AWT event dispatch thread for events that take longer than a certain time to be dispatched

   <source lang="java">
 

/*

* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

import java.awt.*; import java.awt.event.*; import java.lang.management.*; import java.util.*; import java.util.Timer; import javax.swing.*; /**

* Monitors the AWT event dispatch thread for events that take longer than
* a certain time to be dispatched.
* <p/>
* The principle is to record the time at which we start processing an event,
* and have another thread check frequently to see if we"re still processing.
* If the other thread notices that we"ve been processing a single event for
* too long, it prints a stack trace showing what the event dispatch thread
* is doing, and continues to time it until it finally finishes.
* <p/>
* This is useful in determining what code is causing your Java application"s
* GUI to be unresponsive.
* 
*

The original blog can be found here
* *

*
* @author Elliott Hughes <enh@jessies.org>
* 
* Advice, bug fixes, and test cases from
* Alexander Potochkin and Oleg Sukhodolsky.
* 
* https://swinghelper.dev.java.net/
*/

public final class EventDispatchThreadHangMonitor extends EventQueue {

   private static final EventDispatchThreadHangMonitor INSTANCE = new EventDispatchThreadHangMonitor();
   // Time to wait between checks that the event dispatch thread isn"t hung.
   private static final long CHECK_INTERVAL_MS = 100;
   // Maximum time we won"t warn about. This used to be 500 ms, but 1.5 on
   // late-2004 hardware isn"t really up to it; there are too many parts of
   // the JDK that can go away for that long (often code that has to be
   // called on the event dispatch thread, like font loading).
   private static final long UNREASONABLE_DISPATCH_DURATION_MS = 1000;
   // Help distinguish multiple hangs in the log, and match start and end too.
   // Only access this via getNewHangNumber.
   private static int hangCount = 0;
   // Prevents us complaining about hangs during start-up, which are probably
   // the JVM vendor"s fault.
   private boolean haveShownSomeComponent = false;
   // The currently outstanding event dispatches. The implementation of
   // modal dialogs is a common cause for multiple outstanding dispatches.
   private final LinkedList<DispatchInfo> dispatches = new LinkedList<DispatchInfo>();
   private static class DispatchInfo {
       // The last-dumped hung stack trace for this dispatch.
       private StackTraceElement[] lastReportedStack;
       // If so; what was the identifying hang number?
       private int hangNumber;
       // The EDT for this dispatch (for the purpose of getting stack traces).
       // I don"t know of any API for getting the event dispatch thread,
       // but we can assume that it"s the current thread if we"re in the
       // middle of dispatching an AWT event...
       // We can"t cache this because the EDT can die and be replaced by a
       // new EDT if there"s an uncaught exception.
       private final Thread eventDispatchThread = Thread.currentThread();
       // The last time in milliseconds at which we saw a dispatch on the above thread.
       private long lastDispatchTimeMillis = System.currentTimeMillis();
       public DispatchInfo() {
           // All initialization is done by the field initializers.
       }
       public void checkForHang() {
           if (timeSoFar() > UNREASONABLE_DISPATCH_DURATION_MS) {
               examineHang();
           }
       }
       // We can"t use StackTraceElement.equals because that insists on checking the filename and line number.
       // That would be version-specific.
       private static boolean stackTraceElementIs(StackTraceElement e, String className, String methodName, boolean isNative) {
           return e.getClassName().equals(className) && e.getMethodName().equals(methodName) && e.isNativeMethod() == isNative;
       }
       // Checks whether the given stack looks like it"s waiting for another event.
       // This relies on JDK implementation details.
       private boolean isWaitingForNextEvent(StackTraceElement[] currentStack) {
           return stackTraceElementIs(currentStack[0], "java.lang.Object", "wait", true) && stackTraceElementIs(currentStack[1], "java.lang.Object", "wait", false) && stackTraceElementIs(currentStack[2], "java.awt.EventQueue", "getNextEvent", false);
       }
       private void examineHang() {
           StackTraceElement[] currentStack = eventDispatchThread.getStackTrace();
           if (isWaitingForNextEvent(currentStack)) {
               // Don"t be fooled by a modal dialog if it"s waiting for its next event.
               // As long as the modal dialog"s event pump doesn"t get stuck, it"s okay for the outer pump to be suspended.
               return;
           }
           if (stacksEqual(lastReportedStack, currentStack)) {
               // Don"t keep reporting the same hang every time the timer goes off.
               return;
           }
           hangNumber = getNewHangNumber();
           String stackTrace = stackTraceToString(currentStack);
           lastReportedStack = currentStack;
           Log.warn("(hang #" + hangNumber + ") event dispatch thread stuck processing event for " + timeSoFar() + " ms:" + stackTrace);
           checkForDeadlock();
       }
       private static boolean stacksEqual(StackTraceElement[] a, StackTraceElement[] b) {
           if (a == null) {
               return false;
           }
           if (a.length != b.length) {
               return false;
           }
           for (int i = 0; i < a.length; ++i) {
               if (a[i].equals(b[i]) == false) {
                   return false;
               }
           }
           return true;
       }
       /**
        * Returns how long this dispatch has been going on (in milliseconds).
        */
       private long timeSoFar() {
           return (System.currentTimeMillis() - lastDispatchTimeMillis);
       }
       public void dispose() {
           if (lastReportedStack != null) {
               Log.warn("(hang #" + hangNumber + ") event dispatch thread unstuck after " + timeSoFar() + " ms.");
           }
       }
   }
   private EventDispatchThreadHangMonitor() {
       initTimer();
   }
   /**
    * Sets up a timer to check for hangs frequently.
    */
   private void initTimer() {
       final long initialDelayMs = 0;
       final boolean isDaemon = true;
       Timer timer = new Timer("EventDispatchThreadHangMonitor", isDaemon);
       timer.schedule(new HangChecker(), initialDelayMs, CHECK_INTERVAL_MS);
   }
   private class HangChecker extends TimerTask {
       @Override
       public void run() {
           synchronized (dispatches) {
               if (dispatches.isEmpty() || !haveShownSomeComponent) {
                   // Nothing to do.
                   // We don"t destroy the timer when there"s nothing happening
                   // because it would mean a lot more work on every single AWT
                   // event that gets dispatched.
                   return;
               }
               // Only the most recent dispatch can be hung; nested dispatches
               // by their nature cause the outer dispatch pump to be suspended.
               dispatches.getLast().checkForHang();
           }
       }
   }
   /**
    * Sets up hang detection for the event dispatch thread.
    */
   public static void initMonitoring() {
       Toolkit.getDefaultToolkit().getSystemEventQueue().push(INSTANCE);
   }
   /**
    * Overrides EventQueue.dispatchEvent to call our pre and post hooks either
    * side of the system"s event dispatch code.
    */
   @Override
   protected void dispatchEvent(AWTEvent event) {
       try {
           preDispatchEvent();
           super.dispatchEvent(event);
       } finally {
           postDispatchEvent();
           if (!haveShownSomeComponent && 
                   event instanceof WindowEvent && event.getID() == WindowEvent.WINDOW_OPENED) {
               haveShownSomeComponent = true;
           }
       }
   }
   private void debug(String which) {
       if (false) {
           for (int i = dispatches.size(); i >= 0; --i) {
               System.out.print(" ");
           }
           System.out.println(which);
       }
   }
   /**
    * Starts tracking a dispatch.
    */
   private synchronized void preDispatchEvent() {
       debug("pre");
       synchronized (dispatches) {
           dispatches.addLast(new DispatchInfo());
       }
   }
   /**
    * Stops tracking a dispatch.
    */
   private synchronized void postDispatchEvent() {
       synchronized (dispatches) {
           // We"ve finished the most nested dispatch, and don"t need it any longer.
           DispatchInfo justFinishedDispatch = dispatches.removeLast();
           justFinishedDispatch.dispose();
           // The other dispatches, which have been waiting, need to be credited extra time.
           // We do this rather simplistically by pretending they"ve just been redispatched.
           Thread currentEventDispatchThread = Thread.currentThread();
           for (DispatchInfo dispatchInfo : dispatches) {
               if (dispatchInfo.eventDispatchThread == currentEventDispatchThread) {
                   dispatchInfo.lastDispatchTimeMillis = System.currentTimeMillis();
               }
           }
       }
       debug("post");
   }
   private static void checkForDeadlock() {
       ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
       long[] threadIds = threadBean.findMonitorDeadlockedThreads();
       if (threadIds == null) {
           return;
       }
       Log.warn("deadlock detected involving the following threads:");
       ThreadInfo[] threadInfos = threadBean.getThreadInfo(threadIds, Integer.MAX_VALUE);
       for (ThreadInfo info : threadInfos) {
           Log.warn("Thread #" + info.getThreadId() + " " + info.getThreadName() + 
                   " (" + info.getThreadState() + ") waiting on " + info.getLockName() + 
                   " held by " + info.getLockOwnerName() + stackTraceToString(info.getStackTrace()));
       }
   }
   private static String stackTraceToString(StackTraceElement[] stackTrace) {
       StringBuilder result = new StringBuilder();
       // We used to avoid showing any code above where this class gets
       // involved in event dispatch, but that hides potentially useful
       // information when dealing with modal dialogs. Maybe we should
       // reinstate that, but search from the other end of the stack?
       for (StackTraceElement stackTraceElement : stackTrace) {
           String indentation = "    ";
           result.append("\n" + indentation + stackTraceElement);
       }
       return result.toString();
   }
   private synchronized static int getNewHangNumber() {
       return ++hangCount;
   }
   public static void main(String[] args) {
       initMonitoring();
       //special case for deadlock test
       if (args.length > 0 && "deadlock".equals(args[0])) {
           EventDispatchThreadHangMonitor.INSTANCE.haveShownSomeComponent = true;
           Tests.runDeadlockTest();
           return;
       }
       Tests.main(args);
   }
   private static class Tests {
       public static void main(final String[] args) {
           java.awt.EventQueue.invokeLater(new Runnable() {
               public void run() {
                   for (String arg : args) {
                       final JFrame frame = new JFrame();
                       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                       frame.setLocationRelativeTo(null);
                       if (arg.equals("exception")) {
                           runExceptionTest(frame);
                       } else if (arg.equals("focus")) {
                           runFocusTest(frame);
                       } else if (arg.equals("modal-hang")) {
                           runModalTest(frame, true);
                       } else if (arg.equals("modal-no-hang")) {
                           runModalTest(frame, false);
                       } else {
                           System.err.println("unknown regression test "" + arg + """);
                           System.exit(1);
                       }
                       frame.pack();
                       frame.setVisible(true);
                   }
               }
           });
       }
       private static void runDeadlockTest() {
           class Locker {
               private Locker locker;
               public void setLocker(Locker locker) {
                   this.locker = locker;
               }
               public synchronized void tryToDeadlock() {
                   locker.toString();
               }
               public synchronized String toString() {
                   try {
                       Thread.sleep(50);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
                   return super.toString();
               }
           }
           final Locker one = new Locker();
           final Locker two = new Locker();
           one.setLocker(two);
           two.setLocker(one);
           //Deadlock expected here:
           for (int i = 0; i < 100; i++) {
               SwingUtilities.invokeLater(new Runnable() {
                   public void run() {
                       one.tryToDeadlock();
                   }
               });
               two.tryToDeadlock();
           }
       }
       // If we don"t do our post-dispatch activity in a finally block, we"ll
       // report bogus hangs.
       private static void runExceptionTest(final JFrame frame) {
           JButton button = new JButton("Throw Exception");
           button.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e) {
                   // This shouldn"t cause us to report a hang.
                   throw new RuntimeException("Nobody expects the Spanish Inquisition!");
               }
           });
           frame.add(button);
       }
       // A demonstration of nested calls to dispatchEvent caused by SequencedEvent.
       private static void runFocusTest(final JFrame frame) {
           final JDialog dialog = new JDialog(frame, "Non-Modal Dialog");
           dialog.add(new JLabel("Close me!"));
           dialog.pack();
           dialog.setLocationRelativeTo(frame);
           dialog.addWindowFocusListener(new WindowAdapter() {
               public void windowGainedFocus(WindowEvent e) {
                   System.out.println("FocusTest.windowGainedFocus");
                   // If you don"t cope with nested calls to dispatchEvent, you won"t detect this.
                   // See java.awt.SequencedEvent for an example.
                   sleep(2500);
               }
           });
           JButton button = new JButton("Show Non-Modal Dialog");
           button.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e) {
                   dialog.setVisible(true);
               }
           });
           frame.add(button);
       }
       // A demonstration of the problems of dealing with modal dialogs.
       private static void runModalTest(final JFrame frame, final boolean shouldSleep) {
           System.out.println(shouldSleep ? "Expect hangs!" : "There should be no hangs...");
           JButton button = new JButton("Show Modal Dialog");
           button.addActionListener(new ActionListener() {
               public void actionPerformed(ActionEvent e) {
                   if (shouldSleep) {
                       sleep(2500); // This is easy.
                   }
                   JDialog dialog = new JDialog(frame, "Modal dialog", true);
                   dialog.setLayout(new FlowLayout());
                   dialog.add(new JLabel("Close this dialog!"));
                   final JLabel label = new JLabel(" ");
                   dialog.add(label);
                   dialog.pack();
                   dialog.setLocation(frame.getX() - 100, frame.getY());
                   // Make sure the new event pump has some work to do, each unit of which is insufficient to cause a hang.
                   new Thread(new Runnable() {
                       public void run() {
                           for (int i = 0; i <= 100000; ++i) {
                               final int value = i;
                               EventQueue.invokeLater(new Runnable() {
                                   public void run() {
                                       label.setText(Integer.toString(value));
                                   }
                               });
                           }
                       }
                   }).start();
                   dialog.setVisible(true);
                   if (shouldSleep) {
                       sleep(2500); // If you don"t distinguish different stack traces, you won"t report this.
                   }
               }
           });
           frame.add(button);
       }
       private static void sleep(long ms) {
           try {
               System.out.println("Sleeping for " + ms + " ms on " + Thread.currentThread() + "...");
               Thread.sleep(ms);
               System.out.println("Finished sleeping...");
           } catch (Exception ex) {
               ex.printStackTrace();
           }
       }
   }
   private static class Log {
       public static void warn(String str) {
           System.out.println(str);
       }
   }

}


 </source>
   
  
 
  



Multicast event

   <source lang="java">
  

import java.awt.Container; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; public class MulticastEvent extends JPanel implements ActionListener {

 private int counter = 0;
 private JButton closeAllButton;
 public MulticastEvent() {
   JButton newButton = new JButton("New");
   add(newButton);
   newButton.addActionListener(this);
   closeAllButton = new JButton("Close all");
   add(closeAllButton);
 }
 public void actionPerformed(ActionEvent evt) {
   CloseFrame f = new CloseFrame();
   counter++;
   f.setTitle("Window " + counter);
   f.setSize(200, 150);
   f.setLocation(30 * counter, 30 * counter);
   f.show();
   closeAllButton.addActionListener(f);
 }
 public static void main(String[] args) {
   JFrame frame = new JFrame();
   frame.setTitle("MulticastTest");
   frame.setSize(300, 200);
   frame.addWindowListener(new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       System.exit(0);
     }
   });
   Container contentPane = frame.getContentPane();
   contentPane.add(new MulticastEvent());
   frame.show();
 }
 class CloseFrame extends JFrame implements ActionListener {
   public void actionPerformed(ActionEvent evt) { // handles Close all
                           // button
     setVisible(false);
   }
 }

}



 </source>
   
  
 
  



Swing Event MultiListener

   <source lang="java">
  

/* From http://java.sun.ru/docs/books/tutorial/index.html */ /*

* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* -Redistribution of source code must retain the above copyright notice, this
*  list of conditions and the following disclaimer.
*
* -Redistribution in binary form must reproduce the above copyright notice,
*  this list of conditions and the following disclaimer in the documentation
*  and/or other materials provided with the distribution.
*
* Neither the name of Sun Microsystems, Inc. or the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/

/*

* Swing version
*/

import java.awt.Color; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; public class MultiListener extends JPanel implements ActionListener {

 JTextArea topTextArea;
 JTextArea bottomTextArea;
 JButton button1, button2;
 final static String newline = "\n";
 public MultiListener() {
   super(new GridBagLayout());
   GridBagLayout gridbag = (GridBagLayout) getLayout();
   GridBagConstraints c = new GridBagConstraints();
   JLabel l = null;
   c.fill = GridBagConstraints.BOTH;
   c.gridwidth = GridBagConstraints.REMAINDER;
   l = new JLabel("What MultiListener hears:");
   gridbag.setConstraints(l, c);
   add(l);
   c.weighty = 1.0;
   topTextArea = new JTextArea();
   topTextArea.setEditable(false);
   JScrollPane topScrollPane = new JScrollPane(topTextArea);
   Dimension preferredSize = new Dimension(200, 75);
   topScrollPane.setPreferredSize(preferredSize);
   gridbag.setConstraints(topScrollPane, c);
   add(topScrollPane);
   c.weightx = 0.0;
   c.weighty = 0.0;
   l = new JLabel("What Eavesdropper hears:");
   gridbag.setConstraints(l, c);
   add(l);
   c.weighty = 1.0;
   bottomTextArea = new JTextArea();
   bottomTextArea.setEditable(false);
   JScrollPane bottomScrollPane = new JScrollPane(bottomTextArea);
   bottomScrollPane.setPreferredSize(preferredSize);
   gridbag.setConstraints(bottomScrollPane, c);
   add(bottomScrollPane);
   c.weightx = 1.0;
   c.weighty = 0.0;
   c.gridwidth = 1;
   c.insets = new Insets(10, 10, 0, 10);
   button1 = new JButton("Blah blah blah");
   gridbag.setConstraints(button1, c);
   add(button1);
   c.gridwidth = GridBagConstraints.REMAINDER;
   button2 = new JButton("You don"t say!");
   gridbag.setConstraints(button2, c);
   add(button2);
   button1.addActionListener(this);
   button2.addActionListener(this);
   button2.addActionListener(new Eavesdropper(bottomTextArea));
   setPreferredSize(new Dimension(450, 450));
   setBorder(BorderFactory.createCompoundBorder(BorderFactory
       .createMatteBorder(1, 1, 2, 2, Color.black), BorderFactory
       .createEmptyBorder(5, 5, 5, 5)));
 }
 public void actionPerformed(ActionEvent e) {
   topTextArea.append(e.getActionCommand() + newline);
   topTextArea.setCaretPosition(topTextArea.getDocument().getLength());
 }
 /**
  * Create the GUI and show it. For thread safety, this method should be
  * invoked from the event-dispatching thread.
  */
 private static void createAndShowGUI() {
   //Make sure we have nice window decorations.
   JFrame.setDefaultLookAndFeelDecorated(true);
   //Create and set up the window.
   JFrame frame = new JFrame("MultiListener");
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   //Create and set up the content pane.
   JComponent newContentPane = new MultiListener();
   newContentPane.setOpaque(true); //content panes must be opaque
   frame.setContentPane(newContentPane);
   //Display the window.
   frame.pack();
   frame.setVisible(true);
 }
 public static void main(String[] args) {
   //Schedule a job for the event-dispatching thread:
   //creating and showing this application"s GUI.
   javax.swing.SwingUtilities.invokeLater(new Runnable() {
     public void run() {
       createAndShowGUI();
     }
   });
 }

} class Eavesdropper implements ActionListener {

 JTextArea myTextArea;
 public Eavesdropper(JTextArea ta) {
   myTextArea = ta;
 }
 public void actionPerformed(ActionEvent e) {
   myTextArea.append(e.getActionCommand() + MultiListener.newline);
   myTextArea.setCaretPosition(myTextArea.getDocument().getLength());
 }

}



 </source>