1 / 29

Swing Effects

Swing Effects. Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007. What is this about?. Show two sample effects on buttons Show how this can be achieved with UI delegates Discuss alternative implementations. Demo. Possible ways to do this.

Download Presentation

Swing Effects

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Swing Effects Kirill Grouchnikov, Amdocs Desktop Matters Conference San Jose, March 8-9 2007

  2. What is this about? Show two sample effects on buttons Show how this can be achieved with UI delegates Discuss alternative implementations

  3. Demo

  4. Possible ways to do this Custom component – paintComponent Custom repaint manager Custom glass pane Custom UI delegates

  5. Possible ways to do this Custom component – paintComponent Custom repaint manager Custom glass pane Custom UI delegates (*) * - next slides describe the UI delegates approach

  6. How does Swing paint? UI delegates – classes responsible for painting Swing components. The panels are painted by the PanelUI delegate (unless a panel overrides the paintComponent method). The buttons are painted by the ButtonUI delegate (unless a button overrides the paintComponent method).

  7. How is the button painted? JComponent ButtonUI paint() paintComponent() update() paint() layout text/icon paintIcon() paintText() paintFocus() paintBorder() [*] * - this is why you should override paintComponent() and not paint() for custom painting logic. paintChildren() [*]

  8. Icon ghosting - schematics

  9. Icon ghosting - details We add the custom painting code in the following places: ButtonUI.paintIcon – before calling super(), paint the same icon scaled up and translucent (and offset). PanelUI.update – paint the part of the icon that animates outside the child (button) bounds. In addition, a ChangeListener is registered on the button model, tracking changes to the rollover state.

  10. What to keep in mind? The icon is not an Image. Call paintIcon after the Graphics has been scaled and a composite has been applied to it. The ghost image must be centered around the original icon. The ghost effect may “spill” from the immediate parent and overlay sibling components.

  11. ButtonUI code (part I) protected void paintIcon(Graphics g, JComponent c, Rectangle iconRect) { Graphics2D graphics = (Graphics2D) g.create(); FadeTrackerfadeTracker = FadeTracker.getInstance(); AbstractButton b = (AbstractButton) c; if ((ButtonBackgroundDelegate.getKind(b) == ButtonTitleKind.NONE) && fadeTracker.isTracked(c, null, FadeKind.GHOSTING_ICON_ROLLOVER, true)) { float fade10 = fadeTracker.getFade10(c, FadeKind.GHOSTING_ICON_ROLLOVER); // 0.0 --> 0.5 // 10.0 --> 0.0 floatopFactor = -0.5f * fade10 / 10.0f + 0.5f; graphics.setComposite(TransitionLayout.getAlphaComposite(c, opFactor)); Icon icon = SubstanceCoreUtilities.getIcon(b); if (icon != null) {  see the next slide } } graphics.setComposite(TransitionLayout.getAlphaComposite(c)); super.paintIcon(graphics, c, iconRect); graphics.dispose(); } Check if the button has ghost fade animation on the icon Get the current animation position (number between 0.0 and 10.0) Compute the ghost image translucency (fades from 50% to 0% opacity) Set the composite for painting the ghost icon Call super implementation to paint the icon itself

  12. ButtonUI code (part II) double iFactor = 1.0 + fade10 / 10.0; double iWidth = icon.getIconWidth() * iFactor; double iHeight = icon.getIconHeight() * iFactor; BufferedImageiImage = SubstanceCoreUtilities.getBlankImage( (int) iWidth, (int) iHeight); Graphics2D iGraphics = (Graphics2D) iImage.createGraphics(); iGraphics.scale(iFactor, iFactor); icon.paintIcon(b, iGraphics, 0, 0); iGraphics.dispose(); intdx = (int) ((iWidth - icon.getIconWidth()) / 2); intdy = (int) ((iHeight - icon.getIconHeight()) / 2); graphics.drawImage(iImage, iconRect.x - dx, iconRect.y - dy, null); Compute the scale factor and scaled dimensions Create a transparent image Scale its graphics Paint the icon on the scaled graphics (creates the scaled icon) Paint the scaled icon centered around the original icon

  13. Eye candy Icon ghosting over multiple components Press ghosting over multiple components Multiple icon and press ghostings

  14. UI delegates – pros & cons (+) Minimal changes in the application code. (+) No need for custom painting code (+/-) Available only under the specific LAF Can use bytecode injection to change existing third-party LAFs (possible but slightly complicated – stay tuned for more in the future) (-) Handling “spilling” is in container delegates (-) Custom paintComponent implementations

  15. Other approaches How to handle painting order (background, ghost icon, icon+text)? Custom components (+/-) Work under all LAFs (???) (-) Can handle only painting in the component bounds Custom repaint manager (+/-) Work under all LAFs (???) (-) More complicated to write and test (-) Interfere with existing repaint manager (e.g. from SwingX) Custom glass pane (+/-) Work under all LAFs (???) (+/-) Interfere with existing app glass pane (JXLayer approach)

  16. Demo

  17. Additional information Kirill’s blog http://weblogs.java.net/blog/kirillcool Alex’s blog http://weblogs.java.net/blog/alexfromsun Substance LAF project https://substance.dev.java.net Laf-Widget project https://laf-widget.dev.java.net

  18. Q&A kirillcool@yahoo.com

  19. Icon ghosting animation

  20. Container UI code (part I) @Override public void update(Graphics g, JComponent c) { // Paint regular container stuff. In most cases - // background (fill, gradient, watermark) … // Paint ghost images of the animated overlapping // components GhostPaintingUtils.paintGhostImages(c, g); }

  21. Container UI code (part II) public static void paintGhostImages(Component mainComponent, Graphics g) { Graphics2D graphics = (Graphics2D) g.create(); Rectangle panelRect = mainComponent.getBounds(); panelRect.setLocation(mainComponent.getLocationOnScreen()); if (FadeConfigurationManager.getInstance().fadeAllowed( FadeKind.GHOSTING_ICON_ROLLOVER, mainComponent)) { Set<Component> animComps = FadeTracker.getInstance() .getAllComponentsByFadeKind( FadeKind.GHOSTING_ICON_ROLLOVER); for (Component comp : animComps) { // see next slide } } graphics.dispose(); } Work on disposable graphics context Compute screen bounds of the container Check if the icon ghosting animations are allowed Get all components under icon ghosting animations For each such component, do code on next slide

  22. Container UI code (part III) Rectangle compRect = comp.getBounds(); compRect.setLocation(comp.getLocationOnScreen()); intdx = compRect.x - panelRect.x; intdy = compRect.y - panelRect.y; compRect.x -= compRect.width / 2; compRect.y -= compRect.height / 2; compRect.width *= 2; compRect.height *= 2; if (panelRect.intersects(compRect)) { // see next slide } Compute offsets between screen bounds The icon ghosting can take an area twice as large as the component screen bounds Check if container screen bounds and extended screen bounds of the animated component intersect Compute screen bounds of animated component

  23. Container UI code (part IV) float fade10 = FadeTracker.getInstance().getFade10(comp, null, FadeKind.GHOSTING_ICON_ROLLOVER); // 0.0 --> 0.5, 10.0 --> 0.0 float opFactor = 0.5f * (1.0f - fade10 / 10.0f); graphics.setComposite(TransitionLayout.getAlphaComposite(mainComponent, opFactor)); Icon icon = null; Rectangle iconRect = null; if (comp instanceofAbstractButton) { AbstractButton button = (AbstractButton) comp; icon = SubstanceCoreUtilities.getIcon(button, false); iconRect = (Rectangle)button.getClientProperty(SubstanceButtonUI.ICON_RECT); } if ((icon != null) && (iconRect != null)) { // see next slide } Compute the ghost image translucency (fades from 50% to 0% opacity) Get the current animation position Set the composite for painting the ghost icon Get the icon and the icon rectangle

  24. Container UI code (part V) double iFactor = 1.0 + fade10 / 10.0; double iWidth = icon.getIconWidth() * iFactor; double iHeight = icon.getIconHeight() * iFactor; BufferedImageiImage = SubstanceCoreUtilities.getBlankImage((int) iWidth, (int) iHeight); Graphics2D iGraphics = (Graphics2D) iImage.createGraphics(); iGraphics.scale(iFactor, iFactor); icon.paintIcon(comp, iGraphics, 0, 0); iGraphics.dispose(); dx -= (int) ((iWidth - icon.getIconWidth()) / 2); dy -= (int) ((iHeight - icon.getIconHeight()) / 2); graphics.drawImage(iImage, dx + iconRect.x, dy + iconRect.y, null); Compute the scale factor and scaled dimensions Create a transparent image Scale its graphics Paint the icon on the scaled graphics (creates the scaled icon) Paint the scaled icon centered around the original icon (note the computation of icon offsets)

  25. Press ghosting animation

  26. Button press ghosting

  27. What to keep in mind? The ghost image must be centered around the button image. The ghost effect may “spill” from the immediate parent and overlay sibling components.

  28. Container UI code (partial) doubleiFactor = 1.0 + fade10 / 10.0; doubleiWidth = bounds.width * iFactor; doubleiHeight = bounds.height * iFactor; BufferedImageiImage = SubstanceCoreUtilities.getBlankImage( (int) iWidth, (int) iHeight); Graphics2D iGraphics = (Graphics2D)iImage.createGraphics(); iGraphics.scale(iFactor, iFactor); comp.paint(iGraphics); iGraphics.dispose(); dx -= (int) ((iWidth - bounds.width) / 2); dy -= (int) ((iHeight - bounds.height) / 2); graphics.drawImage(iImage, bounds.x - dx, bounds.y - dy, null); Paint the scaled component centered around the original component (note the computation of component offsets) Compute the scale factor and scaled dimensions Create a transparent image Scale its graphics Paint the component on the scaled graphics (creates the scaled component)

  29. Some corner cases Not paint too much (trigger repaint only of the affected area) Handle change in showing / visibility during the animation Account for large button / icons (start from lower alpha) Cache animating child image for reuse during painting in the same animation cycle on different containers

More Related