📄 swingutilities.java
字号:
}
/**
* Compute and return the location of the icons origin, the
* location of origin of the text baseline, and a possibly clipped
* version of the compound labels string. Locations are computed
* relative to the viewR rectangle.
* This layoutCompoundLabel() does not know how to handle LEADING/TRAILING
* values in horizontalTextPosition (they will default to RIGHT) and in
* horizontalAlignment (they will default to CENTER).
* Use the other version of layoutCompoundLabel() instead.
*/
private static String layoutCompoundLabelImpl(
JComponent c,
FontMetrics fm,
String text,
Icon icon,
int verticalAlignment,
int horizontalAlignment,
int verticalTextPosition,
int horizontalTextPosition,
Rectangle viewR,
Rectangle iconR,
Rectangle textR,
int textIconGap)
{
/* Initialize the icon bounds rectangle iconR.
*/
if (icon != null) {
iconR.width = icon.getIconWidth();
iconR.height = icon.getIconHeight();
}
else {
iconR.width = iconR.height = 0;
}
/* Initialize the text bounds rectangle textR. If a null
* or and empty String was specified we substitute "" here
* and use 0,0,0,0 for textR.
*/
boolean textIsEmpty = (text == null) || text.equals("");
View v = null;
if (textIsEmpty) {
textR.width = textR.height = 0;
text = "";
}
else {
v = (c != null) ? (View) c.getClientProperty("html") : null;
if (v != null) {
textR.width = (int) v.getPreferredSpan(View.X_AXIS);
textR.height = (int) v.getPreferredSpan(View.Y_AXIS);
} else {
textR.width = computeStringWidth(fm,text);
textR.height = fm.getHeight();
}
}
/* Unless both text and icon are non-null, we effectively ignore
* the value of textIconGap. The code that follows uses the
* value of gap instead of textIconGap.
*/
int gap = (textIsEmpty || (icon == null)) ? 0 : textIconGap;
if (!textIsEmpty) {
/* If the label text string is too wide to fit within the available
* space "..." and as many characters as will fit will be
* displayed instead.
*/
int availTextWidth;
if (horizontalTextPosition == CENTER) {
availTextWidth = viewR.width;
}
else {
availTextWidth = viewR.width - (iconR.width + gap);
}
if (textR.width > availTextWidth) {
if (v != null) {
textR.width = availTextWidth;
} else {
String clipString = "...";
int totalWidth = computeStringWidth(fm,clipString);
int nChars;
for(nChars = 0; nChars < text.length(); nChars++) {
totalWidth += fm.charWidth(text.charAt(nChars));
if (totalWidth > availTextWidth) {
break;
}
}
text = text.substring(0, nChars) + clipString;
textR.width = computeStringWidth(fm,text);
}
}
}
/* Compute textR.x,y given the verticalTextPosition and
* horizontalTextPosition properties
*/
if (verticalTextPosition == TOP) {
if (horizontalTextPosition != CENTER) {
textR.y = 0;
}
else {
textR.y = -(textR.height + gap);
}
}
else if (verticalTextPosition == CENTER) {
textR.y = (iconR.height / 2) - (textR.height / 2);
}
else { // (verticalTextPosition == BOTTOM)
if (horizontalTextPosition != CENTER) {
textR.y = iconR.height - textR.height;
}
else {
textR.y = (iconR.height + gap);
}
}
if (horizontalTextPosition == LEFT) {
textR.x = -(textR.width + gap);
}
else if (horizontalTextPosition == CENTER) {
textR.x = (iconR.width / 2) - (textR.width / 2);
}
else { // (horizontalTextPosition == RIGHT)
textR.x = (iconR.width + gap);
}
/* labelR is the rectangle that contains iconR and textR.
* Move it to its proper position given the labelAlignment
* properties.
*
* To avoid actually allocating a Rectangle, Rectangle.union
* has been inlined below.
*/
int labelR_x = Math.min(iconR.x, textR.x);
int labelR_width = Math.max(iconR.x + iconR.width,
textR.x + textR.width) - labelR_x;
int labelR_y = Math.min(iconR.y, textR.y);
int labelR_height = Math.max(iconR.y + iconR.height,
textR.y + textR.height) - labelR_y;
int dx, dy;
if (verticalAlignment == TOP) {
dy = viewR.y - labelR_y;
}
else if (verticalAlignment == CENTER) {
dy = (viewR.y + (viewR.height / 2)) - (labelR_y + (labelR_height / 2));
}
else { // (verticalAlignment == BOTTOM)
dy = (viewR.y + viewR.height) - (labelR_y + labelR_height);
}
if (horizontalAlignment == LEFT) {
dx = viewR.x - labelR_x;
}
else if (horizontalAlignment == RIGHT) {
dx = (viewR.x + viewR.width) - (labelR_x + labelR_width);
}
else { // (horizontalAlignment == CENTER)
dx = (viewR.x + (viewR.width / 2)) -
(labelR_x + (labelR_width / 2));
}
/* Translate textR and glypyR by dx,dy.
*/
textR.x += dx;
textR.y += dy;
iconR.x += dx;
iconR.y += dy;
return text;
}
/**
* Paint a component c on an abitrary graphics g in the
* specified rectangle, specifying the rectangle's upper left corner
* and size. The component is reparented to a private
* container (whose parent becomes p) which prevents c.validate() and
* and c.repaint() calls from propogating up the tree. The intermediate
* container has no other effect.
*
* @param g the Graphics object to draw on
* @param c the Component to draw
* @param p the intermedate Container
* @param x an int specifying the left side of the area draw in, in pixels,
* measured from the left edge of the graphics context
* @param y an int specifying the top of the area to draw in, in pixels
* measured down from the top edge of the graphics context
* @param w an int specifying the width of the area draw in, in pixels
* @param h an int specifying the height of the area draw in, in pixels
*/
public static void paintComponent(Graphics g, Component c, Container p, int x, int y, int w, int h) {
getCellRendererPane(c, p).paintComponent(g, c, p, x, y, w, h,false);
}
/**
* Paint a component c on an abitrary graphics g in the
* specified rectangle, specifying a Rectangle object. The component is reparented to a private
* container (whose parent becomes p) which prevents c.validate() and
* and c.repaint() calls from propogating up the tree. The intermediate
* container has no other effect.
*
* @param g the Graphics object to draw on
* @param c the Component to draw
* @param p the intermedate Container
* @param r the Rectangle to draw in
*/
public static void paintComponent(Graphics g, Component c, Container p, Rectangle r) {
paintComponent(g, c, p, r.x, r.y, r.width, r.height);
}
/*
* Ensure that cell renderer c has a ComponentShell parent and that
* the shells parent is p.
*/
private static CellRendererPane getCellRendererPane(Component c, Container p) {
Container shell = c.getParent();
if (shell instanceof CellRendererPane) {
if (shell.getParent() != p) {
p.add(shell);
}
} else {
shell = new CellRendererPane();
shell.add(c);
p.add(shell);
}
return (CellRendererPane)shell;
}
/**
* A simple minded look and feel change: ask each node in the tree
* to updateUI(), i.e. to initialize its UI property with the
* current look and feel.
*/
public static void updateComponentTreeUI(Component c) {
updateComponentTreeUI0(c);
c.invalidate();
c.validate();
c.repaint();
}
private static void updateComponentTreeUI0(Component c) {
if (c instanceof JComponent) {
((JComponent) c).updateUI();
}
Component[] children = null;
if (c instanceof JMenu) {
children = ((JMenu)c).getMenuComponents();
}
else if (c instanceof Container) {
children = ((Container)c).getComponents();
}
if (children != null) {
for(int i = 0; i < children.length; i++) {
updateComponentTreeUI0(children[i]);
}
}
}
/**
* Causes <i>doRun.run()</i> to be executed asynchronously on the
* AWT event dispatching thread. This will happen after all
* pending AWT events have been processed. This method should
* be used when an application thread needs to update the GUI.
* In the following example the invokeAndWait() calls queues
* the doHelloWorld Runnable for the event dispatching thread and
* then prints a message.
* <pre>
* Runnable doHelloWorld = new Runnable() {
* public void run() {
* System.out.println("Hello World on " + Thread.currentThread());
* }
* };
*
* SwingUtilities.invokeAndWait(doHelloWorld);
* System.out.println("Waiting ... ");
* </pre>
* If invokeAndWait is called from the event dispatching thread,
* e.g. from a JButtons ActionListener, the <i>doRun.run()</i> will
* still be deferred till all pending events have been processed.
* Note that if the <i>doRun.run()</i> throws an uncaught exception
* the event dispatching thread will unwind (not the current thread).
* <p>
* Additional documentation and examples for this method can be
* found in <A HREF="http://java.sun.com/products/jfc/swingdoc-archive/threads.html">.
*
* @see #invokeAndWait
*/
public static void invokeLater(Runnable doRun) {
SystemEventQueueUtilities.postRunnable(doRun, null);
}
/**
* Causes <i>doRun.run()</i> to be executed synchronously on the
* AWT event dispatching thread. This call will block until
* all pending AWT events have been processed and (then)
* <i>doRun.run()</i> returns. This method should
* be used when an application thread needs to update the GUI.
* It should not be called from the EventDispatchThread.
* Here's an example that creates a new application thread
* that uses invokeAndWait() to print a string from the event
* dispatching thread and then, when that's finished, print
* a string from the application thread.
* <pre>
* final Runnable doHelloWorld = new Runnable() {
* public void run() {
* System.out.println("Hello World on " + Thread.currentThread());
* }
* };
*
* Thread appThread = new Thread() {
* public void run() {
* try {
* SwingUtilities.invokeAndWait(doHelloWorld);
* }
* catch (Exception e) {
* e.printStackTrace();
* }
* System.out.println("Finished on " + Thread.currentThread());
* }
* };
* appThread.start();
* </pre>
* Note that if the Runnable.run() method throws an uncaught exception
* (on the event dispatching thread) it's caught and rethrown, as
* an InvocationTargetException, on the callers thread.
* <p>
* Additional documentation and examples for this method can be
* found in <A HREF="http://java.sun.com/products/jfc/swingdoc-archive/threads.html">.
*
* @exception InterruptedException If we're interrupted while waiting for
* the event dispatching thread to finish excecuting <i>doRun.run()</i>
* @exception InvocationTargetException If <i>doRun.run()</i> throws
*
* @see #invokeLater
*/
public static void invokeAndWait(final Runnable doRun)
throws InterruptedException, InvocationTargetException
{
if(isEventDispatchThread ()) {
throw new Error("Cannot call invokeAndWait from the event dispatcher thread");
}
Object lock = new Object() {
public String toString() {
return "SwingUtilities.invokeAndWait() lock for " + doRun;
}
};
Exception exc = null;
synchronized(lock) {
exc = SystemEventQueueUtilities.postRunnable(doRun, lock);
lock.wait();
}
if (exc != null) {
throw new InvocationTargetException(exc);
}
}
private static Class eventDispatchThreadClass = null;
/**
* Returns true if the current thread is an AWT event dispatching thread.
* @return true if the current thread is an AWT event dispatching thread
*/
public static boolean isEventDispatchThread()
{
Thread currentThread = Thread.currentThread();
/* The first time we're called on what appears to be the event
* dispatching thread, we stash the threads class in
* eventDispatchThreadClass. Subsequently we effectively
* return eventDispatchThreadClass instanceof Thread.currentThread().
*/
if (eventDispatchThreadClass == null) {
Class currentThreadClass = currentThread.getClass();
/* This test is a crock. It's known to work on all of the popular
* JDK1.1 implementations available as of January 1998.
*/
if((currentThreadClass.getName().indexOf("EventDispatchThread") >= 0) ||
(currentThreadClass.getName().indexOf("JMEventQueue") >= 0)) {
eventDispatchThreadClass = currentThreadClass;
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -