📄 jcomponent.java
字号:
Graphics g2 = getComponentGraphics(g); paintComponent(g2); paintBorder(g2); paintChildren(g2); Rectangle clip = g2.getClipBounds(); if (clip.x == 0 && clip.y == 0 && clip.width == getWidth() && clip.height == getHeight()) RepaintManager.currentManager(this).markCompletelyClean(this); } } /** * Paint the component's border. This usually means calling {@link * Border#paintBorder} on the {@link #border} property, if it is * non-<code>null</code>. You may override this if you wish to customize * border painting behavior. The border is painted after the component's * body, but before the component's children. * * @param g The graphics context with which to paint the border * * @see #paint * @see #paintChildren * @see #paintComponent */ protected void paintBorder(Graphics g) { if (getBorder() != null) getBorder().paintBorder(this, g, 0, 0, getWidth(), getHeight()); } /** * Paint the component's children. This usually means calling {@link * Container#paint}, which recursively calls {@link #paint} on any of the * component's children, with appropriate changes to coordinate space and * clipping region. You may override this if you wish to customize * children painting behavior. The children are painted after the * component's body and border. * * @param g The graphics context with which to paint the children * * @see #paint * @see #paintBorder * @see #paintComponent */ protected void paintChildren(Graphics g) { Shape originalClip = g.getClip(); Rectangle inner = SwingUtilities.calculateInnerArea(this, rectCache); g.clipRect(inner.x, inner.y, inner.width, inner.height); Component[] children = getComponents(); // Find the bottommost component that needs to be painted. This is a // component that completely covers the current clip and is opaque. In // this case we don't need to paint the components below it. int startIndex = children.length - 1; // No need to check for overlapping components when this component is // optimizedDrawingEnabled (== it tiles its children). if (! isOptimizedDrawingEnabled()) { Rectangle clip = g.getClipBounds(); for (int i = 0; i < children.length; i++) { Rectangle childBounds = children[i].getBounds(); if (children[i].isOpaque() && SwingUtilities.isRectangleContainingRectangle(childBounds, g.getClipBounds())) { startIndex = i; break; } } } // paintingTile becomes true just before we start painting the component's // children. paintingTile = true; for (int i = startIndex; i >= 0; --i) { // paintingTile must be set to false before we begin to start painting // the last tile. if (i == 0) paintingTile = false; if (!children[i].isVisible()) continue; Rectangle bounds = children[i].getBounds(rectCache); Rectangle oldClip = g.getClipBounds(); if (oldClip == null) oldClip = bounds; if (!g.hitClip(bounds.x, bounds.y, bounds.width, bounds.height)) continue; boolean translated = false; try { g.clipRect(bounds.x, bounds.y, bounds.width, bounds.height); g.translate(bounds.x, bounds.y); translated = true; children[i].paint(g); } finally { if (translated) g.translate(-bounds.x, -bounds.y); g.setClip(oldClip); } } g.setClip(originalClip); } /** * Paint the component's body. This usually means calling {@link * ComponentUI#update} on the {@link #ui} property of the component, if * it is non-<code>null</code>. You may override this if you wish to * customize the component's body-painting behavior. The component's body * is painted first, before the border and children. * * @param g The graphics context with which to paint the body * * @see #paint * @see #paintBorder * @see #paintChildren */ protected void paintComponent(Graphics g) { if (ui != null) { Graphics g2 = g; if (!(g instanceof Graphics2D)) g2 = g.create(); ui.update(g2, this); if (!(g instanceof Graphics2D)) g2.dispose(); } } /** * A variant of {@link #paintImmediately(Rectangle)} which takes * integer parameters. * * @param x The left x coordinate of the dirty region * @param y The top y coordinate of the dirty region * @param w The width of the dirty region * @param h The height of the dirty region */ public void paintImmediately(int x, int y, int w, int h) { paintImmediately(new Rectangle(x, y, w, h)); } /** * Transform the provided dirty rectangle for this component into the * appropriate ancestral {@link JRootPane} and call {@link #paint} on * that root pane. This method is called from the {@link RepaintManager} * and should always be called within the painting thread. * * <p>This method will acquire a double buffer from the {@link * RepaintManager} if the component's {@link #doubleBuffered} property is * <code>true</code> and the <code>paint</code> call is the * <em>first</em> recursive <code>paint</code> call inside swing.</p> * * <p>The method will also modify the provided {@link Graphics} context * via the {@link #getComponentGraphics} method. If you want to customize * the graphics object used for painting, you should override that method * rather than <code>paint</code>.</p> * * @param r The dirty rectangle to paint */ public void paintImmediately(Rectangle r) { // Try to find a root pane for this component. //Component root = findPaintRoot(r); Component root = findPaintRoot(r); // If no paint root is found, then this component is completely overlapped // by another component and we don't need repainting. if (root == null) return; if (root == null || !root.isShowing()) return; Rectangle rootClip = SwingUtilities.convertRectangle(this, r, root); if (root instanceof JComponent) ((JComponent) root).paintImmediately2(rootClip); else root.repaint(rootClip.x, rootClip.y, rootClip.width, rootClip.height); } /** * Performs the actual work of paintImmediatly on the repaint root. * * @param r the area to be repainted */ void paintImmediately2(Rectangle r) { RepaintManager rm = RepaintManager.currentManager(this); Graphics g = getGraphics(); g.setClip(r.x, r.y, r.width, r.height); if (rm.isDoubleBufferingEnabled() && isDoubleBuffered()) paintDoubleBuffered(g); else paintSimple(g); g.dispose(); } /** * Performs double buffered repainting. * * @param g the graphics context to paint to */ void paintDoubleBuffered(Graphics g) { Rectangle r = g.getClipBounds(); if (r == null) r = new Rectangle(0, 0, getWidth(), getHeight()); RepaintManager rm = RepaintManager.currentManager(this); // Paint on the offscreen buffer. Image buffer = rm.getOffscreenBuffer(this, getWidth(), getHeight()); Graphics g2 = buffer.getGraphics(); g2 = getComponentGraphics(g2); g2.setClip(r.x, r.y, r.width, r.height); isPaintingDoubleBuffered = true; try { paint(g2); } finally { isPaintingDoubleBuffered = false; g2.dispose(); } // Paint the buffer contents on screen. g.drawImage(buffer, 0, 0, this); } /** * Performs normal painting without double buffering. * * @param g the graphics context to use */ void paintSimple(Graphics g) { Graphics g2 = getComponentGraphics(g); paint(g2); } /** * Return a string representation for this component, for use in * debugging. * * @return A string describing this component. */ protected String paramString() { StringBuffer sb = new StringBuffer(); sb.append(super.paramString()); sb.append(",alignmentX=").append(getAlignmentX()); sb.append(",alignmentY=").append(getAlignmentY()); sb.append(",border="); if (getBorder() != null) sb.append(getBorder()); sb.append(",maximumSize="); if (getMaximumSize() != null) sb.append(getMaximumSize()); sb.append(",minimumSize="); if (getMinimumSize() != null) sb.append(getMinimumSize()); sb.append(",preferredSize="); if (getPreferredSize() != null) sb.append(getPreferredSize()); return sb.toString(); } /** * A variant of {@link * #registerKeyboardAction(ActionListener,String,KeyStroke,int)} which * provides <code>null</code> for the command name. */ public void registerKeyboardAction(ActionListener act, KeyStroke stroke, int cond) { registerKeyboardAction(act, null, stroke, cond); } /* * There is some charmingly undocumented behavior sun seems to be using * to simulate the old register/unregister keyboard binding API. It's not * clear to me why this matters, but we shall endeavour to follow suit. * * Two main thing seem to be happening when you do registerKeyboardAction(): * * - no actionMap() entry gets created, just an entry in inputMap() * * - the inputMap() entry is a proxy class which invokes the the * binding's actionListener as a target, and which clobbers the command * name sent in the ActionEvent, providing the binding command name * instead. * * This much you can work out just by asking the input and action maps * what they contain after making bindings, and watching the event which * gets delivered to the recipient. Beyond that, it seems to be a * sun-private solution so I will only immitate it as much as it matters * to external observers. */ private static class ActionListenerProxy extends AbstractAction { ActionListener target; String bindingCommandName; public ActionListenerProxy(ActionListener li, String cmd) { target = li; bindingCommandName = cmd; } public void actionPerformed(ActionEvent e) { ActionEvent derivedEvent = new ActionEvent(e.getSource(), e.getID(), bindingCommandName, e.getModifiers()); target.actionPerformed(derivedEvent); } } /** * An obsolete method to register a keyboard action on this component. * You should use <code>getInputMap</code> and <code>getActionMap</code> * to fetch mapping tables from keystrokes to commands, and commands to * actions, respectively, and modify those mappings directly. * * @param act The action to be registered * @param cmd The command to deliver in the delivered {@link * java.awt.event.ActionEvent} * @param stroke The keystroke to register on * @param cond One of the values {@link #UNDEFINED_CONDITION}, * {@link #WHEN_ANCESTOR_OF_FOCUSED_COMPONENT}, {@link #WHEN_FOCUSED}, or * {@link #WHEN_IN_FOCUSED_WINDOW}, indicating the condition which must * be met for the action to be fired * * @see #unregisterKeyboardAction * @see #getConditionForKeyStroke * @see #resetKeyboardActions */ public void registerKeyboardAction(ActionListener act, String cmd, KeyStroke stroke, int cond) { getInputMap(cond).put(stroke, new ActionListenerProxy(act, cmd)); } public final void setInputMap(int condition, InputMap map) { enableEvents(AWTEvent.KEY_EVENT_MASK); switch (condition) { case WHEN_FOCUSED: inputMap_whenFocused = map; break; case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: inputMap_whenAncestorOfFocused = map; break; case WHEN_IN_FOCUSED_WINDOW: if (map != null && !(map instanceof ComponentInputMap)) throw new IllegalArgumentException("WHEN_IN_FOCUSED_WINDOW " + "InputMap must be a ComponentInputMap"); inputMap_whenInFocusedWindow = (ComponentInputMap)map; break; case UNDEFINED_CONDITION: default: throw new IllegalArgumentException(); } } public final InputMap getInputMap(int condition) { enableEvents(AWTEvent.KEY_EVENT_MASK); switch (condition) { case WHEN_FOCUSED: if (inputMap_whenFocused == null) inputMap_whenFocused = new InputMap(); return inputMap_whenFocused; case WHEN_ANCESTOR_OF_FOCUSED_COMPONENT: if (inputMap_whenAncestorOfFocused == null) inputMap_whenAncestorOfFocused = new InputMap(); return inputMap_whenAncestorOfFocused; case WHEN_IN_FOCUSED_WINDOW: if (inputMap_whenInFocusedWindow == null) inputMap_whenInFocusedWindow = new ComponentInputMap(this); return inputMap_whenInFocusedWindow; case UNDEFINED_CONDITION: default: return null; } } public final InputMap getInputMap() { return getInputMap(WHEN_FOCUSED); } public final ActionMap getActionMap() { if (actionMap == null) actionMap = new ActionMap(); re
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -