Java/Swing JFC/Swing Utilities
Версия от 18:01, 31 мая 2010; (обсуждение)
Содержание
- 1 Center that window on the given desktop.
- 2 Change the sizes of all the passed buttons to be the size of the largest one.
- 3 Convert a coordinate on a screen to a coordinate relative to a component"s bounds
- 4 Convert a coordinate relative to a component"s bounds to screen coordinates
- 5 Converts a Swing key stroke descriptor to a familiar Emacs-like name
- 6 Get Owning Frame for Component
- 7 Get Screen Bounds For
- 8 Getting the JFrame of a Component
- 9 Get Top Frame
- 10 Get Top Level Ancestor
- 11 Handle long-running tasks in a Swing application
- 12 Returns the usable area of the screen
- 13 Swing invoke and wait
- 14 Swing invoke later
- 15 Swing Utilities getWindowAncestor
- 16 Swing worker Example
Center that window on the given desktop.
/*
* $Id: WindowUtils.java,v 1.16 2009/05/25 16:37:52 kschaefe Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* 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.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Rectangle;
import javax.swing.JInternalFrame;
/**
* Encapsulates various utilities for windows (ie: <code>Frame</code> and
* <code>Dialog</code> objects and descendants, in particular).
*
* @author Richard Bair
*/
public class Utils {
/**
* <p/>
* Returns the <code>Point</code> at which a window should be placed to
* center that window on the given desktop.
* </p>
* <p/>
* Some thought was taken as to whether to implement a method such as this,
* or to simply make a method that, given a window, will center it. It was
* decided that it is better to not alter an object within a method.
* </p>
*
* @param window The window (JInternalFrame) to calculate the center point
* for. This object can not be null.
*
* @return the <code>Point</code> at which the window should be placed to
* center that window on the given desktop
*/
public static Point getPointForCentering(JInternalFrame window) {
try {
//assert window != null;
Point mousePoint = MouseInfo.getPointerInfo().getLocation();
GraphicsDevice[] devices = GraphicsEnvironment
.getLocalGraphicsEnvironment().getScreenDevices();
for (GraphicsDevice device : devices) {
Rectangle bounds = device.getDefaultConfiguration().getBounds();
//check to see if the mouse cursor is within these bounds
if (mousePoint.x >= bounds.x && mousePoint.y >= bounds.y
&& mousePoint.x <= (bounds.x + bounds.width)
&& mousePoint.y <= (bounds.y + bounds.height)) {
//this is it
int screenWidth = bounds.width;
int screenHeight = bounds.height;
int width = window.getWidth();
int height = window.getHeight();
return new Point(((screenWidth - width) / 2) + bounds.x,
((screenHeight - height) / 2) + bounds
.y);
}
}
} catch (Exception e) {
}
return new Point(0, 0);
}
}
Change the sizes of all the passed buttons to be the size of the largest one.
/*
* Copyright (C) 2001-2004 Colin Bell
* colbell@users.sourceforge.net
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyVetoException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
/**
* Common GUI utilities accessed via static methods.
*
* @author
*/
public class GUIUtils {
/**
* Change the sizes of all the passed buttons to be the size of the largest
* one.
*
* @param btns
* Array of buttons to eb resized.
*
* @throws IllegalArgumentException
* If <TT>btns</TT> is <TT>null</TT>.
*/
public static void setJButtonSizesTheSame(JButton[] btns) {
if (btns == null) {
throw new IllegalArgumentException("null JButton[] passed");
}
// Get the largest width and height
final Dimension maxSize = new Dimension(0, 0);
for (int i = 0; i < btns.length; ++i) {
final JButton btn = btns[i];
final FontMetrics fm = btn.getFontMetrics(btn.getFont());
Rectangle2D bounds = fm.getStringBounds(btn.getText(), btn.getGraphics());
int boundsHeight = (int) bounds.getHeight();
int boundsWidth = (int) bounds.getWidth();
maxSize.width = boundsWidth > maxSize.width ? boundsWidth : maxSize.width;
maxSize.height = boundsHeight > maxSize.height ? boundsHeight : maxSize.height;
}
Insets insets = btns[0].getInsets();
maxSize.width += insets.left + insets.right;
maxSize.height += insets.top + insets.bottom;
for (int i = 0; i < btns.length; ++i) {
JButton btn = btns[i];
btn.setPreferredSize(maxSize);
}
}
}
Convert a coordinate on a screen to a coordinate relative to a component"s bounds
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
public class Main {
public static void main(String[] argv) {
JButton component = new JButton();
Point pt = new Point(component.getLocation());
SwingUtilities.convertPointFromScreen(pt, component);
}
}
Convert a coordinate relative to a component"s bounds to screen coordinates
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.SwingUtilities;
public class Main {
public static void main(String[] argv) {
JButton component = new JButton();
Point pt = new Point(component.getLocation());
SwingUtilities.convertPointToScreen(pt, component);
}
}
Converts a Swing key stroke descriptor to a familiar Emacs-like name
/*
* $Id: Utilities.java,v 1.11 2008/10/14 22:31:46 rah003 Exp $
*
* Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* 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.ruponent;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
/**
* Contribution from NetBeans: Issue #319-swingx.
* <p>
*
* PENDING: need to reconcile with OS, JVM... added as-is because needed the
* shortcut handling to fix #
*
* @author apple
*/
public class Utilities {
private Utilities() {
}
private static final int CTRL_WILDCARD_MASK = 32768;
private static final int ALT_WILDCARD_MASK = CTRL_WILDCARD_MASK * 2;
/** Operating system is Windows NT. */
public static final int OS_WINNT = 1 << 0;
/** Operating system is Windows 95. */
public static final int OS_WIN95 = OS_WINNT << 1;
/** Operating system is Windows 98. */
public static final int OS_WIN98 = OS_WIN95 << 1;
/** Operating system is Solaris. */
public static final int OS_SOLARIS = OS_WIN98 << 1;
/** Operating system is Linux. */
public static final int OS_LINUX = OS_SOLARIS << 1;
/** Operating system is HP-UX. */
public static final int OS_HP = OS_LINUX << 1;
/** Operating system is IBM AIX. */
public static final int OS_AIX = OS_HP << 1;
/** Operating system is SGI IRIX. */
public static final int OS_IRIX = OS_AIX << 1;
/** Operating system is Sun OS. */
public static final int OS_SUNOS = OS_IRIX << 1;
/** Operating system is Compaq TRU64 Unix */
public static final int OS_TRU64 = OS_SUNOS << 1;
/** Operating system is OS/2. */
public static final int OS_OS2 = OS_TRU64 << 2;
/** Operating system is Mac. */
public static final int OS_MAC = OS_OS2 << 1;
/** Operating system is Windows 2000. */
public static final int OS_WIN2000 = OS_MAC << 1;
/** Operating system is Compaq OpenVMS */
public static final int OS_VMS = OS_WIN2000 << 1;
/**
*Operating system is one of the Windows variants but we don"t know which
*one it is
*/
public static final int OS_WIN_OTHER = OS_VMS << 1;
/** Operating system is unknown. */
public static final int OS_OTHER = OS_WIN_OTHER << 1;
/** Operating system is FreeBSD
* @since 4.50
*/
public static final int OS_FREEBSD = OS_OTHER << 1;
/** A mask for Windows platforms. */
public static final int OS_WINDOWS_MASK = OS_WINNT | OS_WIN95 | OS_WIN98 | OS_WIN2000 | OS_WIN_OTHER;
/** A mask for Unix platforms. */
public static final int OS_UNIX_MASK = OS_SOLARIS | OS_LINUX | OS_HP | OS_AIX | OS_IRIX | OS_SUNOS | OS_TRU64 |
OS_MAC | OS_FREEBSD;
/** A height of the windows"s taskbar */
public static final int TYPICAL_WINDOWS_TASKBAR_HEIGHT = 27;
/** A height of the Mac OS X"s menu */
private static final int TYPICAL_MACOSX_MENU_HEIGHT = 24;
private static int operatingSystem = -1;
/** reference to map that maps allowed key names to their values (String, Integer)
and reference to map for mapping of values to their names */
private static Reference<Object> namesAndValues;
/** Get the operating system.
* @return one of the <code>OS_*</code> constants (such as {@link #OS_WINNT})
*/
public static int getOperatingSystem() {
if (operatingSystem == -1) {
String osName = System.getProperty("os.name");
if ("Windows NT".equals(osName)) { // NOI18N
operatingSystem = OS_WINNT;
} else if ("Windows 95".equals(osName)) { // NOI18N
operatingSystem = OS_WIN95;
} else if ("Windows 98".equals(osName)) { // NOI18N
operatingSystem = OS_WIN98;
} else if ("Windows 2000".equals(osName)) { // NOI18N
operatingSystem = OS_WIN2000;
} else if (osName.startsWith("Windows ")) { // NOI18N
operatingSystem = OS_WIN_OTHER;
} else if ("Solaris".equals(osName)) { // NOI18N
operatingSystem = OS_SOLARIS;
} else if (osName.startsWith("SunOS")) { // NOI18N
operatingSystem = OS_SOLARIS;
}
// JDK 1.4 b2 defines os.name for me as "Redhat Linux" -jglick
else if (osName.endsWith("Linux")) { // NOI18N
operatingSystem = OS_LINUX;
} else if ("HP-UX".equals(osName)) { // NOI18N
operatingSystem = OS_HP;
} else if ("AIX".equals(osName)) { // NOI18N
operatingSystem = OS_AIX;
} else if ("Irix".equals(osName)) { // NOI18N
operatingSystem = OS_IRIX;
} else if ("SunOS".equals(osName)) { // NOI18N
operatingSystem = OS_SUNOS;
} else if ("Digital UNIX".equals(osName)) { // NOI18N
operatingSystem = OS_TRU64;
} else if ("OS/2".equals(osName)) { // NOI18N
operatingSystem = OS_OS2;
} else if ("OpenVMS".equals(osName)) { // NOI18N
operatingSystem = OS_VMS;
} else if (osName.equals("Mac OS X")) { // NOI18N
operatingSystem = OS_MAC;
} else if (osName.startsWith("Darwin")) { // NOI18N
operatingSystem = OS_MAC;
} else if (osName.toLowerCase(Locale.US).startsWith("freebsd")) { // NOI18N
operatingSystem = OS_FREEBSD;
} else {
operatingSystem = OS_OTHER;
}
}
return operatingSystem;
}
/**
* Finds out the monitor where the user currently has the input focus.
* This method is usually used to help the client code to figure out on
* which monitor it should place newly created windows/frames/dialogs.
*
* @return the GraphicsConfiguration of the monitor which currently has the
* input focus
*/
private static GraphicsConfiguration getCurrentGraphicsConfiguration() {
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (focusOwner != null) {
Window w = SwingUtilities.getWindowAncestor(focusOwner);
if (w != null) {
return w.getGraphicsConfiguration();
}
}
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
/**
* Returns the usable area of the screen where applications can place its
* windows. The method subtracts from the screen the area of taskbars,
* system menus and the like. The screen this method applies to is the one
* which is considered current, ussually the one where the current input
* focus is.
*
* @return the rectangle of the screen where one can place windows
*
* @since 2.5
*/
public static Rectangle getUsableScreenBounds() {
return getUsableScreenBounds(getCurrentGraphicsConfiguration());
}
/**
* Returns the usable area of the screen where applications can place its
* windows. The method subtracts from the screen the area of taskbars,
* system menus and the like.
*
* @param gconf the GraphicsConfiguration of the monitor
* @return the rectangle of the screen where one can place windows
*
* @since 2.5
*/
public static Rectangle getUsableScreenBounds(GraphicsConfiguration gconf) {
if (gconf == null) {
gconf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
Rectangle bounds = new Rectangle(gconf.getBounds());
String str;
str = System.getProperty("netbeans.screen.insets"); // NOI18N
if (str != null) {
StringTokenizer st = new StringTokenizer(str, ", "); // NOI18N
if (st.countTokens() == 4) {
try {
bounds.y = Integer.parseInt(st.nextToken());
bounds.x = Integer.parseInt(st.nextToken());
bounds.height -= (bounds.y + Integer.parseInt(st.nextToken()));
bounds.width -= (bounds.x + Integer.parseInt(st.nextToken()));
} catch (NumberFormatException ex) {
Logger.getAnonymousLogger().log(Level.WARNING, null, ex);
}
}
return bounds;
}
str = System.getProperty("netbeans.taskbar.height"); // NOI18N
if (str != null) {
bounds.height -= Integer.getInteger(str, 0).intValue();
return bounds;
}
try {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Insets insets = toolkit.getScreenInsets(gconf);
bounds.y += insets.top;
bounds.x += insets.left;
bounds.height -= (insets.top + insets.bottom);
bounds.width -= (insets.left + insets.right);
} catch (Exception ex) {
Logger.getAnonymousLogger().log(Level.WARNING, null, ex);
}
return bounds;
}
/** Initialization of the names and values
* @return array of two hashmaps first maps
* allowed key names to their values (String, Integer)
* and second
* hashtable for mapping of values to their names (Integer, String)
*/
private static synchronized HashMap[] initNameAndValues() {
if (namesAndValues != null) {
HashMap[] arr = (HashMap[]) namesAndValues.get();
if (arr != null) {
return arr;
}
}
Field[] fields;
// JW - fix Issue #353-swingx: play nicer inside sandbox.
try {
fields = KeyEvent.class.getDeclaredFields();
// fields = KeyEvent.class.getFields();
} catch (SecurityException e) {
// JW: need to do better? What are the use-cases where we don"t have
// any access to the fields?
fields = new Field[0];
}
HashMap<String,Integer> names = new HashMap<String,Integer>(((fields.length * 4) / 3) + 5, 0.75f);
HashMap<Integer,String> values = new HashMap<Integer,String>(((fields.length * 4) / 3) + 5, 0.75f);
for (int i = 0; i < fields.length; i++) {
if (Modifier.isStatic(fields[i].getModifiers())) {
String name = fields[i].getName();
if (name.startsWith("VK_")) { // NOI18N
// exclude VK
name = name.substring(3);
try {
int numb = fields[i].getInt(null);
Integer value = new Integer(numb);
names.put(name, value);
values.put(value, name);
} catch (IllegalArgumentException ex) {
} catch (IllegalAccessException ex) {
}
}
}
}
if (names.get("CONTEXT_MENU") == null) { // NOI18N
Integer n = new Integer(0x20C);
names.put("CONTEXT_MENU", n); // NOI18N
values.put(n, "CONTEXT_MENU"); // NOI18N
n = new Integer(0x20D);
names.put("WINDOWS", n); // NOI18N
values.put(n, "WINDOWS"); // NOI18N
}
HashMap[] arr = { names, values };
namesAndValues = new SoftReference<Object>(arr);
return arr;
}
/** Converts a Swing key stroke descriptor to a familiar Emacs-like name.
* @param stroke key description
* @return name of the key (e.g. <code>CS-F1</code> for control-shift-function key one)
* @see #stringToKey
*/
public static String keyToString(KeyStroke stroke) {
StringBuffer sb = new StringBuffer();
// add modifiers that must be pressed
if (addModifiers(sb, stroke.getModifiers())) {
sb.append("-");
}
HashMap[] namesAndValues = initNameAndValues();
String c = (String) namesAndValues[1].get(new Integer(stroke.getKeyCode()));
if (c == null) {
sb.append(stroke.getKeyChar());
} else {
sb.append(c);
}
return sb.toString();
}
/** Construct a new key description from a given universal string
* description.
* Provides mapping between Emacs-like textual key descriptions and the
* <code>KeyStroke</code> object used in Swing.
* <P>
* This format has following form:
* <P><code>[C][A][S][M]-<em>identifier</em></code>
* <p>Where:
* <UL>
* <LI> <code>C</code> stands for the Control key
* <LI> <code>A</code> stands for the Alt key
* <LI> <code>S</code> stands for the Shift key
* <LI> <code>M</code> stands for the Meta key
* </UL>
* The format also supports two wildcard codes, to support differences in
* platforms. These are the preferred choices for registering keystrokes,
* since platform conflicts will automatically be handled:
* <UL>
* <LI> <code>D</code> stands for the default menu accelerator - the Control
* key on most platforms, the Command (meta) key on Macintosh</LI>
* <LI> <code>O</code> stands for the alternate accelerator - the Alt key on
* most platforms, the Ctrl key on Macintosh (Macintosh uses Alt as a
* secondary shift key for composing international characters - if you bind
* Alt-8 to an action, a mac user with a French keyboard will not be able
* to type the <code>[</code> character, which is a significant handicap</LI>
* </UL>
* If you use the wildcard characters, and specify a key which will conflict
* with keys the operating system consumes, it will be mapped to whichever
* choice can work - for example, on Macintosh, Command-Q is always consumed
* by the operating system, so <code>D-Q</code> will always map to Control-Q.
* <p>
* Every modifier before the hyphen must be pressed.
* <em>identifier</EM> can be any text constant from {@link KeyEvent} but
* without the leading <code>VK_</code> characters. So {@link KeyEvent#VK_ENTER} is described as
* <code>ENTER</code>.
*
* @param s the string with the description of the key
* @return key description object, or <code>null</code> if the string does not represent any valid key
*/
public static KeyStroke stringToKey(String s) {
StringTokenizer st = new StringTokenizer(s.toUpperCase(Locale.ENGLISH), "-", true); // NOI18N
int needed = 0;
HashMap names = initNameAndValues()[0];
int lastModif = -1;
try {
for (;;) {
String el = st.nextToken();
// required key
if (el.equals("-")) { // NOI18N
if (lastModif != -1) {
needed |= lastModif;
lastModif = -1;
}
continue;
}
// if there is more elements
if (st.hasMoreElements()) {
// the text should describe modifiers
lastModif = readModifiers(el);
} else {
// last text must be the key code
Integer i = (Integer) names.get(el);
boolean wildcard = (needed & CTRL_WILDCARD_MASK) != 0;
//Strip out the explicit mask - KeyStroke won"t know
//what to do with it
needed = needed & ~CTRL_WILDCARD_MASK;
boolean macAlt = (needed & ALT_WILDCARD_MASK) != 0;
needed = needed & ~ALT_WILDCARD_MASK;
if (i != null) {
//#26854 - Default accelerator should be Command on mac
if (wildcard) {
needed |= getMenuShortCutKeyMask();
if ((getOperatingSystem() & OS_MAC) != 0) {
if (!usableKeyOnMac(i.intValue(), needed)) {
needed &= ~getMenuShortCutKeyMask();
needed |= KeyEvent.CTRL_MASK;
}
}
}
if (macAlt) {
if (getOperatingSystem() == OS_MAC) {
needed |= KeyEvent.CTRL_MASK;
} else {
needed |= KeyEvent.ALT_MASK;
}
}
return KeyStroke.getKeyStroke(i.intValue(), needed);
} else {
return null;
}
}
}
} catch (NoSuchElementException ex) {
return null;
}
}
/**
* need to guard against headlessExceptions when testing.
* @return the acceletor mask for shortcuts.
*/
private static int getMenuShortCutKeyMask() {
if (GraphicsEnvironment.isHeadless()) {
return ((getOperatingSystem() & OS_MAC) != 0) ?
KeyEvent.META_MASK : KeyEvent.CTRL_MASK;
}
return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
}
private static boolean usableKeyOnMac(int key, int mask) {
//All permutations fail for Q except ctrl
if (key == KeyEvent.VK_Q) {
return false;
}
boolean isMeta = ((mask & KeyEvent.META_MASK) != 0) || ((mask & KeyEvent.CTRL_DOWN_MASK) != 0);
boolean isAlt = ((mask & KeyEvent.ALT_MASK) != 0) || ((mask & KeyEvent.ALT_DOWN_MASK) != 0);
boolean isOnlyMeta = isMeta && ((mask & ~(KeyEvent.META_DOWN_MASK | KeyEvent.META_MASK)) == 0);
//Mac OS consumes keys Command+ these keys - the app will never see
//them, so CTRL should not be remapped for these
if (isOnlyMeta) {
return (key != KeyEvent.VK_H) && (key != KeyEvent.VK_SPACE) && (key != KeyEvent.VK_TAB);
} else return !((key == KeyEvent.VK_D) && isMeta && isAlt);
}
/** Convert a space-separated list of Emacs-like key binding names to a list of Swing key strokes.
* @param s the string with keys
* @return array of key strokes, or <code>null</code> if the string description is not valid
* @see #stringToKey
*/
public static KeyStroke[] stringToKeys(String s) {
StringTokenizer st = new StringTokenizer(s.toUpperCase(Locale.ENGLISH), " "); // NOI18N
ArrayList<KeyStroke> arr = new ArrayList<KeyStroke>();
while (st.hasMoreElements()) {
s = st.nextToken();
KeyStroke k = stringToKey(s);
if (k == null) {
return null;
}
arr.add(k);
}
return arr.toArray(new KeyStroke[arr.size()]);
}
/** Adds characters for modifiers to the buffer.
* @param buf buffer to add to
* @param modif modifiers to add (KeyEvent.XXX_MASK)
* @return true if something has been added
*/
private static boolean addModifiers(StringBuffer buf, int modif) {
boolean b = false;
if ((modif & KeyEvent.CTRL_MASK) != 0) {
buf.append("C"); // NOI18N
b = true;
}
if ((modif & KeyEvent.ALT_MASK) != 0) {
buf.append("A"); // NOI18N
b = true;
}
if ((modif & KeyEvent.SHIFT_MASK) != 0) {
buf.append("S"); // NOI18N
b = true;
}
if ((modif & KeyEvent.META_MASK) != 0) {
buf.append("M"); // NOI18N
b = true;
}
if ((modif & CTRL_WILDCARD_MASK) != 0) {
buf.append("D");
b = true;
}
if ((modif & ALT_WILDCARD_MASK) != 0) {
buf.append("O");
b = true;
}
return b;
}
/** Reads for modifiers and creates integer with required mask.
* @param s string with modifiers
* @return integer with mask
* @exception NoSuchElementException if some letter is not modifier
*/
private static int readModifiers(String s) throws NoSuchElementException {
int m = 0;
for (int i = 0; i < s.length(); i++) {
switch (s.charAt(i)) {
case "C":
m |= KeyEvent.CTRL_MASK;
break;
case "A":
m |= KeyEvent.ALT_MASK;
break;
case "M":
m |= KeyEvent.META_MASK;
break;
case "S":
m |= KeyEvent.SHIFT_MASK;
break;
case "D":
m |= CTRL_WILDCARD_MASK;
break;
case "O":
m |= ALT_WILDCARD_MASK;
break;
default:
throw new NoSuchElementException(s);
}
}
return m;
}
}
Get Owning Frame for Component
/*
* Copyright (C) 2001-2004 Colin Bell
* colbell@users.sourceforge.net
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.ruponent;
import java.awt.Frame;
import javax.swing.SwingUtilities;
/**
* Common GUI utilities accessed via static methods.
*
* @author
*/
public class GUIUtils {
/**
* Return the owning <CODE>Frame</CODE> for the passed component of <CODE>null</CODE>
* if it doesn"t have one.
*
* @throws IllegalArgumentException
* If <TT>wind</TT> is <TT>null</TT>.
*/
public static Frame getOwningFrame(Component comp) {
if (comp == null) {
throw new IllegalArgumentException("null Component passed");
}
if (comp instanceof Frame) {
return (Frame) comp;
}
return getOwningFrame(SwingUtilities.windowForComponent(comp));
}
}
Get Screen Bounds For
/*
* Copyright (C) 2001-2004 Colin Bell
* colbell@users.sourceforge.net
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyVetoException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JInternalFrame;
import javax.swing.SwingUtilities;
/**
* Common GUI utilities accessed via static methods.
*
* @author
*/
public class GUIUtils {
public static Rectangle getScreenBoundsFor(Rectangle rc) {
final GraphicsDevice[] gds = GraphicsEnvironment.getLocalGraphicsEnvironment()
.getScreenDevices();
final List<GraphicsConfiguration> configs = new ArrayList<GraphicsConfiguration>();
for (int i = 0; i < gds.length; i++) {
GraphicsConfiguration gc = gds[i].getDefaultConfiguration();
if (rc.intersects(gc.getBounds())) {
configs.add(gc);
}
}
GraphicsConfiguration selected = null;
if (configs.size() > 0) {
for (Iterator<GraphicsConfiguration> it = configs.iterator(); it.hasNext();) {
GraphicsConfiguration gcc = it.next();
if (selected == null)
selected = gcc;
else {
if (gcc.getBounds().contains(rc.x + 20, rc.y + 20)) {
selected = gcc;
break;
}
}
}
} else {
selected = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice()
.getDefaultConfiguration();
}
int x = selected.getBounds().x;
int y = selected.getBounds().y;
int w = selected.getBounds().width;
int h = selected.getBounds().height;
return new Rectangle(x, y, w, h);
}
}
Getting the JFrame of a Component
import java.awt.ruponent;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.SwingUtilities;
public class Main {
public static void main(String[] argv) throws Exception {
// Create an action
Action action = new AbstractAction("Action Label") {
// This method is called when the action is triggered
public void actionPerformed(ActionEvent evt) {
Component c = (Component) evt.getSource();
// Get the frame
Component frame = SwingUtilities.getRoot(c);
// Hide the frame
frame.setVisible(false);
}
};
}
}
Get Top Frame
/*
GNU LESSER GENERAL PUBLIC LICENSE
Copyright (C) 2006 The Lobo Project
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
Contact info: lobochief@users.sourceforge.net
*/
import java.awt.*;
public class GUITasks {
public static Frame getTopFrame() {
Frame[] frames = Frame.getFrames();
for(int i = 0; i < frames.length; i++) {
if(frames[i].getFocusOwner() != null) {
return frames[i];
}
}
if(frames.length > 0) {
return frames[0];
}
return null;
}
public static void drawDashed(Graphics g, int x1, int y1, int x2, int y2, int dashSize, int gapSize) {
if(x2 < x1) {
int temp = x1;
x1 = x2;
x2 = temp;
}
if(y2 < y1) {
int temp = y1;
y1 = y2;
y2 = temp;
}
int totalDash = dashSize + gapSize;
if(y1 == y2) {
int virtualStartX = (x1 / totalDash) * totalDash;
for(int x = virtualStartX; x < x2; x += totalDash) {
int topX = x + dashSize;
if(topX > x2) {
topX = x2;
}
int firstX = x;
if(firstX < x1) {
firstX = x1;
}
if(firstX < topX) {
g.drawLine(firstX, y1, topX, y1);
}
}
}
else if(x1 == x2) {
int virtualStartY = (y1 / totalDash) * totalDash;
for(int y = virtualStartY; y < y2; y += totalDash) {
int topY = y + dashSize;
if(topY > y2) {
topY = y2;
}
int firstY = y;
if(firstY < y1) {
firstY = y1;
}
if(firstY < topY) {
g.drawLine(x1, firstY, x1, topY);
}
}
}
else {
// Not supported
g.drawLine(x1, y1, x2, y2);
}
}
}
Get Top Level Ancestor
import java.applet.Applet;
import java.awt.ruponent;
import java.awt.Container;
import java.awt.Point;
import java.awt.Window;
import java.util.ArrayList;
import javax.swing.RootPaneContainer;
import javax.swing.SwingUtilities;
/**
* Copyright (C) 2004 NNL Technology AB
* Visit www.infonode.net for information about InfoNode(R)
* products and how to contact NNL Technology AB.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston,
* MA 02111-1307, USA.
*/
// $Id: ComponentUtil.java,v 1.25 2005/12/04 13:46:04 jesper Exp $
public class Util {
public static Component getTopLevelAncestor(Component c) {
while (c != null) {
if (c instanceof Window || c instanceof Applet)
break;
c = c.getParent();
}
return c;
}
}
Handle long-running tasks in a Swing application
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class Main {
private static JButton good = new JButton("Good");
private static JLabel resultLabel = new JLabel("Ready", JLabel.CENTER);
public static void main(String[] args) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p = new JPanel();
p.setOpaque(true);
p.setLayout(new FlowLayout());
p.add(good);
f.add(p, BorderLayout.CENTER);
f.add(resultLabel, BorderLayout.SOUTH);
good.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ev) {
resultLabel.setText("Working . . .");
good.setEnabled(false);
Thread worker = new Thread() {
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
resultLabel.setText("Ready");
good.setEnabled(true);
}
});
}
};
worker.start(); // So we don"t hold up the dispatch thread.
}
});
f.setSize(300, 100);
f.setVisible(true);
}
}
Returns the usable area of the screen
/*
* $Id: Utilities.java,v 1.11 2008/10/14 22:31:46 rah003 Exp $
*
* Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* 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.ruponent;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.KeyEvent;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.BreakIterator;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
/**
* Contribution from NetBeans: Issue #319-swingx.
* <p>
*
* PENDING: need to reconcile with OS, JVM... added as-is because needed the
* shortcut handling to fix #
*
* @author apple
*/
public class Utilities {
private Utilities() {
}
private static final int CTRL_WILDCARD_MASK = 32768;
private static final int ALT_WILDCARD_MASK = CTRL_WILDCARD_MASK * 2;
/** Operating system is Windows NT. */
public static final int OS_WINNT = 1 << 0;
/** Operating system is Windows 95. */
public static final int OS_WIN95 = OS_WINNT << 1;
/** Operating system is Windows 98. */
public static final int OS_WIN98 = OS_WIN95 << 1;
/** Operating system is Solaris. */
public static final int OS_SOLARIS = OS_WIN98 << 1;
/** Operating system is Linux. */
public static final int OS_LINUX = OS_SOLARIS << 1;
/** Operating system is HP-UX. */
public static final int OS_HP = OS_LINUX << 1;
/** Operating system is IBM AIX. */
public static final int OS_AIX = OS_HP << 1;
/** Operating system is SGI IRIX. */
public static final int OS_IRIX = OS_AIX << 1;
/** Operating system is Sun OS. */
public static final int OS_SUNOS = OS_IRIX << 1;
/** Operating system is Compaq TRU64 Unix */
public static final int OS_TRU64 = OS_SUNOS << 1;
/** Operating system is OS/2. */
public static final int OS_OS2 = OS_TRU64 << 2;
/** Operating system is Mac. */
public static final int OS_MAC = OS_OS2 << 1;
/** Operating system is Windows 2000. */
public static final int OS_WIN2000 = OS_MAC << 1;
/** Operating system is Compaq OpenVMS */
public static final int OS_VMS = OS_WIN2000 << 1;
/**
*Operating system is one of the Windows variants but we don"t know which
*one it is
*/
public static final int OS_WIN_OTHER = OS_VMS << 1;
/** Operating system is unknown. */
public static final int OS_OTHER = OS_WIN_OTHER << 1;
/** Operating system is FreeBSD
* @since 4.50
*/
public static final int OS_FREEBSD = OS_OTHER << 1;
/** A mask for Windows platforms. */
public static final int OS_WINDOWS_MASK = OS_WINNT | OS_WIN95 | OS_WIN98 | OS_WIN2000 | OS_WIN_OTHER;
/** A mask for Unix platforms. */
public static final int OS_UNIX_MASK = OS_SOLARIS | OS_LINUX | OS_HP | OS_AIX | OS_IRIX | OS_SUNOS | OS_TRU64 |
OS_MAC | OS_FREEBSD;
/** A height of the windows"s taskbar */
public static final int TYPICAL_WINDOWS_TASKBAR_HEIGHT = 27;
/** A height of the Mac OS X"s menu */
private static final int TYPICAL_MACOSX_MENU_HEIGHT = 24;
private static int operatingSystem = -1;
/** reference to map that maps allowed key names to their values (String, Integer)
and reference to map for mapping of values to their names */
private static Reference<Object> namesAndValues;
/** Get the operating system.
* @return one of the <code>OS_*</code> constants (such as {@link #OS_WINNT})
*/
public static int getOperatingSystem() {
if (operatingSystem == -1) {
String osName = System.getProperty("os.name");
if ("Windows NT".equals(osName)) { // NOI18N
operatingSystem = OS_WINNT;
} else if ("Windows 95".equals(osName)) { // NOI18N
operatingSystem = OS_WIN95;
} else if ("Windows 98".equals(osName)) { // NOI18N
operatingSystem = OS_WIN98;
} else if ("Windows 2000".equals(osName)) { // NOI18N
operatingSystem = OS_WIN2000;
} else if (osName.startsWith("Windows ")) { // NOI18N
operatingSystem = OS_WIN_OTHER;
} else if ("Solaris".equals(osName)) { // NOI18N
operatingSystem = OS_SOLARIS;
} else if (osName.startsWith("SunOS")) { // NOI18N
operatingSystem = OS_SOLARIS;
}
// JDK 1.4 b2 defines os.name for me as "Redhat Linux" -jglick
else if (osName.endsWith("Linux")) { // NOI18N
operatingSystem = OS_LINUX;
} else if ("HP-UX".equals(osName)) { // NOI18N
operatingSystem = OS_HP;
} else if ("AIX".equals(osName)) { // NOI18N
operatingSystem = OS_AIX;
} else if ("Irix".equals(osName)) { // NOI18N
operatingSystem = OS_IRIX;
} else if ("SunOS".equals(osName)) { // NOI18N
operatingSystem = OS_SUNOS;
} else if ("Digital UNIX".equals(osName)) { // NOI18N
operatingSystem = OS_TRU64;
} else if ("OS/2".equals(osName)) { // NOI18N
operatingSystem = OS_OS2;
} else if ("OpenVMS".equals(osName)) { // NOI18N
operatingSystem = OS_VMS;
} else if (osName.equals("Mac OS X")) { // NOI18N
operatingSystem = OS_MAC;
} else if (osName.startsWith("Darwin")) { // NOI18N
operatingSystem = OS_MAC;
} else if (osName.toLowerCase(Locale.US).startsWith("freebsd")) { // NOI18N
operatingSystem = OS_FREEBSD;
} else {
operatingSystem = OS_OTHER;
}
}
return operatingSystem;
}
/**
* Finds out the monitor where the user currently has the input focus.
* This method is usually used to help the client code to figure out on
* which monitor it should place newly created windows/frames/dialogs.
*
* @return the GraphicsConfiguration of the monitor which currently has the
* input focus
*/
private static GraphicsConfiguration getCurrentGraphicsConfiguration() {
Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
if (focusOwner != null) {
Window w = SwingUtilities.getWindowAncestor(focusOwner);
if (w != null) {
return w.getGraphicsConfiguration();
}
}
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
/**
* Returns the usable area of the screen where applications can place its
* windows. The method subtracts from the screen the area of taskbars,
* system menus and the like. The screen this method applies to is the one
* which is considered current, ussually the one where the current input
* focus is.
*
* @return the rectangle of the screen where one can place windows
*
* @since 2.5
*/
public static Rectangle getUsableScreenBounds() {
return getUsableScreenBounds(getCurrentGraphicsConfiguration());
}
/**
* Returns the usable area of the screen where applications can place its
* windows. The method subtracts from the screen the area of taskbars,
* system menus and the like.
*
* @param gconf the GraphicsConfiguration of the monitor
* @return the rectangle of the screen where one can place windows
*
* @since 2.5
*/
public static Rectangle getUsableScreenBounds(GraphicsConfiguration gconf) {
if (gconf == null) {
gconf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
Rectangle bounds = new Rectangle(gconf.getBounds());
String str;
str = System.getProperty("netbeans.screen.insets"); // NOI18N
if (str != null) {
StringTokenizer st = new StringTokenizer(str, ", "); // NOI18N
if (st.countTokens() == 4) {
try {
bounds.y = Integer.parseInt(st.nextToken());
bounds.x = Integer.parseInt(st.nextToken());
bounds.height -= (bounds.y + Integer.parseInt(st.nextToken()));
bounds.width -= (bounds.x + Integer.parseInt(st.nextToken()));
} catch (NumberFormatException ex) {
Logger.getAnonymousLogger().log(Level.WARNING, null, ex);
}
}
return bounds;
}
str = System.getProperty("netbeans.taskbar.height"); // NOI18N
if (str != null) {
bounds.height -= Integer.getInteger(str, 0).intValue();
return bounds;
}
try {
Toolkit toolkit = Toolkit.getDefaultToolkit();
Insets insets = toolkit.getScreenInsets(gconf);
bounds.y += insets.top;
bounds.x += insets.left;
bounds.height -= (insets.top + insets.bottom);
bounds.width -= (insets.left + insets.right);
} catch (Exception ex) {
Logger.getAnonymousLogger().log(Level.WARNING, null, ex);
}
return bounds;
}
/** Initialization of the names and values
* @return array of two hashmaps first maps
* allowed key names to their values (String, Integer)
* and second
* hashtable for mapping of values to their names (Integer, String)
*/
private static synchronized HashMap[] initNameAndValues() {
if (namesAndValues != null) {
HashMap[] arr = (HashMap[]) namesAndValues.get();
if (arr != null) {
return arr;
}
}
Field[] fields;
// JW - fix Issue #353-swingx: play nicer inside sandbox.
try {
fields = KeyEvent.class.getDeclaredFields();
// fields = KeyEvent.class.getFields();
} catch (SecurityException e) {
// JW: need to do better? What are the use-cases where we don"t have
// any access to the fields?
fields = new Field[0];
}
HashMap<String,Integer> names = new HashMap<String,Integer>(((fields.length * 4) / 3) + 5, 0.75f);
HashMap<Integer,String> values = new HashMap<Integer,String>(((fields.length * 4) / 3) + 5, 0.75f);
for (int i = 0; i < fields.length; i++) {
if (Modifier.isStatic(fields[i].getModifiers())) {
String name = fields[i].getName();
if (name.startsWith("VK_")) { // NOI18N
// exclude VK
name = name.substring(3);
try {
int numb = fields[i].getInt(null);
Integer value = new Integer(numb);
names.put(name, value);
values.put(value, name);
} catch (IllegalArgumentException ex) {
} catch (IllegalAccessException ex) {
}
}
}
}
if (names.get("CONTEXT_MENU") == null) { // NOI18N
Integer n = new Integer(0x20C);
names.put("CONTEXT_MENU", n); // NOI18N
values.put(n, "CONTEXT_MENU"); // NOI18N
n = new Integer(0x20D);
names.put("WINDOWS", n); // NOI18N
values.put(n, "WINDOWS"); // NOI18N
}
HashMap[] arr = { names, values };
namesAndValues = new SoftReference<Object>(arr);
return arr;
}
/** Converts a Swing key stroke descriptor to a familiar Emacs-like name.
* @param stroke key description
* @return name of the key (e.g. <code>CS-F1</code> for control-shift-function key one)
* @see #stringToKey
*/
public static String keyToString(KeyStroke stroke) {
StringBuffer sb = new StringBuffer();
// add modifiers that must be pressed
if (addModifiers(sb, stroke.getModifiers())) {
sb.append("-");
}
HashMap[] namesAndValues = initNameAndValues();
String c = (String) namesAndValues[1].get(new Integer(stroke.getKeyCode()));
if (c == null) {
sb.append(stroke.getKeyChar());
} else {
sb.append(c);
}
return sb.toString();
}
/** Construct a new key description from a given universal string
* description.
* Provides mapping between Emacs-like textual key descriptions and the
* <code>KeyStroke</code> object used in Swing.
* <P>
* This format has following form:
* <P><code>[C][A][S][M]-<em>identifier</em></code>
* <p>Where:
* <UL>
* <LI> <code>C</code> stands for the Control key
* <LI> <code>A</code> stands for the Alt key
* <LI> <code>S</code> stands for the Shift key
* <LI> <code>M</code> stands for the Meta key
* </UL>
* The format also supports two wildcard codes, to support differences in
* platforms. These are the preferred choices for registering keystrokes,
* since platform conflicts will automatically be handled:
* <UL>
* <LI> <code>D</code> stands for the default menu accelerator - the Control
* key on most platforms, the Command (meta) key on Macintosh</LI>
* <LI> <code>O</code> stands for the alternate accelerator - the Alt key on
* most platforms, the Ctrl key on Macintosh (Macintosh uses Alt as a
* secondary shift key for composing international characters - if you bind
* Alt-8 to an action, a mac user with a French keyboard will not be able
* to type the <code>[</code> character, which is a significant handicap</LI>
* </UL>
* If you use the wildcard characters, and specify a key which will conflict
* with keys the operating system consumes, it will be mapped to whichever
* choice can work - for example, on Macintosh, Command-Q is always consumed
* by the operating system, so <code>D-Q</code> will always map to Control-Q.
* <p>
* Every modifier before the hyphen must be pressed.
* <em>identifier</EM> can be any text constant from {@link KeyEvent} but
* without the leading <code>VK_</code> characters. So {@link KeyEvent#VK_ENTER} is described as
* <code>ENTER</code>.
*
* @param s the string with the description of the key
* @return key description object, or <code>null</code> if the string does not represent any valid key
*/
public static KeyStroke stringToKey(String s) {
StringTokenizer st = new StringTokenizer(s.toUpperCase(Locale.ENGLISH), "-", true); // NOI18N
int needed = 0;
HashMap names = initNameAndValues()[0];
int lastModif = -1;
try {
for (;;) {
String el = st.nextToken();
// required key
if (el.equals("-")) { // NOI18N
if (lastModif != -1) {
needed |= lastModif;
lastModif = -1;
}
continue;
}
// if there is more elements
if (st.hasMoreElements()) {
// the text should describe modifiers
lastModif = readModifiers(el);
} else {
// last text must be the key code
Integer i = (Integer) names.get(el);
boolean wildcard = (needed & CTRL_WILDCARD_MASK) != 0;
//Strip out the explicit mask - KeyStroke won"t know
//what to do with it
needed = needed & ~CTRL_WILDCARD_MASK;
boolean macAlt = (needed & ALT_WILDCARD_MASK) != 0;
needed = needed & ~ALT_WILDCARD_MASK;
if (i != null) {
//#26854 - Default accelerator should be Command on mac
if (wildcard) {
needed |= getMenuShortCutKeyMask();
if ((getOperatingSystem() & OS_MAC) != 0) {
if (!usableKeyOnMac(i.intValue(), needed)) {
needed &= ~getMenuShortCutKeyMask();
needed |= KeyEvent.CTRL_MASK;
}
}
}
if (macAlt) {
if (getOperatingSystem() == OS_MAC) {
needed |= KeyEvent.CTRL_MASK;
} else {
needed |= KeyEvent.ALT_MASK;
}
}
return KeyStroke.getKeyStroke(i.intValue(), needed);
} else {
return null;
}
}
}
} catch (NoSuchElementException ex) {
return null;
}
}
/**
* need to guard against headlessExceptions when testing.
* @return the acceletor mask for shortcuts.
*/
private static int getMenuShortCutKeyMask() {
if (GraphicsEnvironment.isHeadless()) {
return ((getOperatingSystem() & OS_MAC) != 0) ?
KeyEvent.META_MASK : KeyEvent.CTRL_MASK;
}
return Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
}
private static boolean usableKeyOnMac(int key, int mask) {
//All permutations fail for Q except ctrl
if (key == KeyEvent.VK_Q) {
return false;
}
boolean isMeta = ((mask & KeyEvent.META_MASK) != 0) || ((mask & KeyEvent.CTRL_DOWN_MASK) != 0);
boolean isAlt = ((mask & KeyEvent.ALT_MASK) != 0) || ((mask & KeyEvent.ALT_DOWN_MASK) != 0);
boolean isOnlyMeta = isMeta && ((mask & ~(KeyEvent.META_DOWN_MASK | KeyEvent.META_MASK)) == 0);
//Mac OS consumes keys Command+ these keys - the app will never see
//them, so CTRL should not be remapped for these
if (isOnlyMeta) {
return (key != KeyEvent.VK_H) && (key != KeyEvent.VK_SPACE) && (key != KeyEvent.VK_TAB);
} else return !((key == KeyEvent.VK_D) && isMeta && isAlt);
}
/** Convert a space-separated list of Emacs-like key binding names to a list of Swing key strokes.
* @param s the string with keys
* @return array of key strokes, or <code>null</code> if the string description is not valid
* @see #stringToKey
*/
public static KeyStroke[] stringToKeys(String s) {
StringTokenizer st = new StringTokenizer(s.toUpperCase(Locale.ENGLISH), " "); // NOI18N
ArrayList<KeyStroke> arr = new ArrayList<KeyStroke>();
while (st.hasMoreElements()) {
s = st.nextToken();
KeyStroke k = stringToKey(s);
if (k == null) {
return null;
}
arr.add(k);
}
return arr.toArray(new KeyStroke[arr.size()]);
}
/** Adds characters for modifiers to the buffer.
* @param buf buffer to add to
* @param modif modifiers to add (KeyEvent.XXX_MASK)
* @return true if something has been added
*/
private static boolean addModifiers(StringBuffer buf, int modif) {
boolean b = false;
if ((modif & KeyEvent.CTRL_MASK) != 0) {
buf.append("C"); // NOI18N
b = true;
}
if ((modif & KeyEvent.ALT_MASK) != 0) {
buf.append("A"); // NOI18N
b = true;
}
if ((modif & KeyEvent.SHIFT_MASK) != 0) {
buf.append("S"); // NOI18N
b = true;
}
if ((modif & KeyEvent.META_MASK) != 0) {
buf.append("M"); // NOI18N
b = true;
}
if ((modif & CTRL_WILDCARD_MASK) != 0) {
buf.append("D");
b = true;
}
if ((modif & ALT_WILDCARD_MASK) != 0) {
buf.append("O");
b = true;
}
return b;
}
/** Reads for modifiers and creates integer with required mask.
* @param s string with modifiers
* @return integer with mask
* @exception NoSuchElementException if some letter is not modifier
*/
private static int readModifiers(String s) throws NoSuchElementException {
int m = 0;
for (int i = 0; i < s.length(); i++) {
switch (s.charAt(i)) {
case "C":
m |= KeyEvent.CTRL_MASK;
break;
case "A":
m |= KeyEvent.ALT_MASK;
break;
case "M":
m |= KeyEvent.META_MASK;
break;
case "S":
m |= KeyEvent.SHIFT_MASK;
break;
case "D":
m |= CTRL_WILDCARD_MASK;
break;
case "O":
m |= ALT_WILDCARD_MASK;
break;
default:
throw new NoSuchElementException(s);
}
}
return m;
}
}
Swing invoke and wait
/*
Code from Desktop Java Live Source
URL: http://www.sourcebeat.ru/downloads/
*/
import javax.swing.*;
import java.lang.reflect.InvocationTargetException;
public class InvokeAndWaitExample extends JPanel {
private Thread progressThread;
private JProgressBar progressBar;
private boolean keepRunning;
public InvokeAndWaitExample() {
this.keepRunning = true;
this.progressThread = new ProgressThread();
this.progressBar = new JProgressBar();
this.progressBar.setMaximum(100);
add(this.progressBar);
System.out.println(keepRunning);
this.progressThread.start();
}
private class ProgressThread extends Thread {
public void run() {
int count = 0;
while (keepRunning) {
try {
Thread.sleep(40);
} catch (InterruptedException e) {
}
final int cval = count;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setValue(cval);
}
});
count++;
if (count == 101) {
count = 0;
} else if (count == 50) {
final int[] returnValue = new int[1];
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
returnValue[0] = JOptionPane.showConfirmDialog(progressBar, "Would you like to reset progress?", "Prompt", JOptionPane.YES_NO_OPTION);
}
});
if (returnValue[0] == JOptionPane.YES_OPTION) {
count = 0;
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] a){
JFrame f = new JFrame();
f.setDefaultCloseOperation(1);
f.add(new InvokeAndWaitExample());
f.pack();
f.setVisible(true);
}
}
Swing invoke later
/*
Code from Desktop Java Live Source
URL: http://www.sourcebeat.ru/downloads/
*/
import javax.swing.*;
import java.awt.event.ActionEvent;
public class InvokeLaterExample extends JPanel {
private JLabel statusArea;
private DefaultListModel listModel;
public InvokeLaterExample() {
JButton button = new JButton(new LongRunningModelFillAction());
add(button);
JList list = new JList();
this.listModel = new DefaultListModel();
this.listModel.addElement("An Empty List Model");
list.setModel(listModel);
add(new JScrollPane(list));
add(new JLabel("Status:"));
this.statusArea = new JLabel();
add(this.statusArea);
}
private class LongRunningModelFillAction extends AbstractAction {
public LongRunningModelFillAction() {
super("Fill Model");
}
public void actionPerformed(ActionEvent e) {
InvokeLaterExample.this.listModel.removeAllElements();
InvokeLaterExample.this.listModel.addElement("Calculating...");
PopulationRunnable populationRunnable = new PopulationRunnable();
Thread populationThread = new Thread(populationRunnable);
populationThread.start();
}
}
private class PopulationRunnable implements Runnable {
public void run() {
final Object[] values = new Object[100];
for (int i = 1; i <= 100; i++) {
values[i - 1] = "Value" + i;
if ((i % 10) == 0) {
final int progress = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
InvokeLaterExample.this.statusArea.setText("Calculated " + progress);
}
});
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
InvokeLaterExample.this.statusArea.setText("");
InvokeLaterExample.this.listModel.removeAllElements();
for (int i = 0; i < values.length; i++) {
InvokeLaterExample.this.listModel.addElement(values[i]);
}
}
});
}
}
public static void main(String[] a){
JFrame f = new JFrame();
f.setDefaultCloseOperation(1);
f.add(new InvokeLaterExample());
f.pack();
f.setVisible(true);
}
}
Swing Utilities getWindowAncestor
/*
Code from Desktop Java Live Source
URL: http://www.sourcebeat.ru/downloads/
*/
import javax.swing.*;
import java.awt.event.ActionEvent;
public class DialogBlockingExample {
public static JPanel createPanel() {
JPanel panel = new JPanel();
JButton button = new JButton(new DialogAction(panel));
panel.add(button);
return panel;
}
private static class DialogAction extends AbstractAction {
private JPanel panel;
public DialogAction(JPanel panel) {
super("Open Dialog");
this.panel = panel;
}
public void actionPerformed(ActionEvent e) {
JDialog dialog = new JDialog((JFrame) SwingUtilities.getWindowAncestor(panel), true);
dialog.getContentPane().add(new JLabel("A Dialog"));
dialog.setVisible(true);
putValue(Action.NAME, "Dialog Already Shown");
}
}
public static void main(String[] a){
JFrame f = new JFrame();
f.setDefaultCloseOperation(1);
f.add(createPanel());
f.pack();
f.setVisible(true);
}
}
Swing worker Example
import javax.swing.*;
import java.awt.event.ActionEvent;
public class SwingWorkerExample extends JPanel {
private JLabel statusArea;
private DefaultListModel listModel;
public SwingWorkerExample() {
JButton button = new JButton(new LongRunningModelFillAction());
add(button);
JList list = new JList();
this.listModel = new DefaultListModel();
this.listModel.addElement("An Empty List Model");
list.setModel(listModel);
add(new JScrollPane(list));
add(new JLabel("Status:"));
this.statusArea = new JLabel();
add(this.statusArea);
}
private class LongRunningModelFillAction extends AbstractAction {
public LongRunningModelFillAction() {
super("Fill Model");
}
public void actionPerformed(ActionEvent e) {
PopulationWorker populationWorker = new PopulationWorker();
populationWorker.start();
}
}
private class PopulationWorker extends SwingWorker {
public Object construct() {
Object[] values = new Object[100];
for (int i = 1; i <= 100; i++) {
values[i - 1] = "Value" + i;
if ((i % 10) == 0) {
final int progress = i;
SwingUtilities.invokeLater(new Runnable() {
public void run() {
SwingWorkerExample.this.statusArea.setText("Calculated " + progress);
}
});
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
return values;
}
public void start() {
SwingWorkerExample.this.listModel.removeAllElements();
SwingWorkerExample.this.listModel.addElement("Calculating...");
super.start();
}
public void finished() {
SwingWorkerExample.this.statusArea.setText("");
SwingWorkerExample.this.listModel.removeAllElements();
Object[] values = (Object[]) getValue();
for (int i = 0; i < values.length; i++) {
SwingWorkerExample.this.listModel.addElement(values[i]);
}
}
}
public static void main(String[] a){
JFrame f = new JFrame();
f.setDefaultCloseOperation(1);
f.add(new SwingWorkerExample());
f.pack();
f.setVisible(true);
}
}
/*
* $Id: SwingWorker.java,v 1.1.1.1 2004/06/16 01:43:39 davidson1 Exp $
*
* Copyright 2004 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*/
/**
* This is the 3rd version of SwingWorker (also known as
* SwingWorker 3), an abstract class that you subclass to
* perform GUI-related work in a dedicated thread. For
* instructions on using this class, see:
*
* http://java.sun.ru/docs/books/tutorial/uiswing/misc/threads.html
*
* Note that the API changed slightly in the 3rd version:
* You must now invoke start() on the SwingWorker after
* creating it.
*/
abstract class SwingWorker {
private Object value; // see getValue(), setValue()
private Thread thread;
/**
* Class to maintain reference to current worker thread
* under separate synchronization control.
*/
private static class ThreadVar {
private Thread thread;
ThreadVar(Thread t) { thread = t; }
synchronized Thread get() { return thread; }
synchronized void clear() { thread = null; }
}
private ThreadVar threadVar;
/**
* Get the value produced by the worker thread, or null if it
* hasn"t been constructed yet.
*/
protected synchronized Object getValue() {
return value;
}
/**
* Set the value produced by worker thread
*/
private synchronized void setValue(Object x) {
value = x;
}
/**
* Compute the value to be returned by the <code>get</code> method.
*/
public abstract Object construct();
/**
* Called on the event dispatching thread (not on the worker thread)
* after the <code>construct</code> method has returned.
*/
public void finished() {
}
/**
* A new method that interrupts the worker thread. Call this method
* to force the worker to stop what it"s doing.
*/
public void interrupt() {
Thread t = threadVar.get();
if (t != null) {
t.interrupt();
}
threadVar.clear();
}
/**
* Return the value created by the <code>construct</code> method.
* Returns null if either the constructing thread or the current
* thread was interrupted before a value was produced.
*
* @return the value created by the <code>construct</code> method
*/
public Object get() {
while (true) {
Thread t = threadVar.get();
if (t == null) {
return getValue();
}
try {
t.join();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt(); // propagate
return null;
}
}
}
/**
* Start a thread that will call the <code>construct</code> method
* and then exit.
*/
public SwingWorker() {
final Runnable doFinished = new Runnable() {
public void run() { finished(); }
};
Runnable doConstruct = new Runnable() {
public void run() {
try {
setValue(construct());
}
finally {
threadVar.clear();
}
SwingUtilities.invokeLater(doFinished);
}
};
Thread t = new Thread(doConstruct);
threadVar = new ThreadVar(t);
}
/**
* Start the worker thread.
*/
public void start() {
Thread t = threadVar.get();
if (t != null) {
t.start();
}
}
}