Java/Event/General Event
Содержание
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>