Transparent and irregular swing windows

Source: Internet
Author: User
Tags gety
Transparent and irregular swing windows








 
 

Print-friendly version



By Kirill grouchnikov,
4/22/08

 

Support for transparent and irregular windows has become AWT and swing
Features that the Team has long dreamed. Although the local application has been using this feature on the main operating system for a long time, it is not available in core Java. Coming soon
"Consumer JRE" is being modified, that is, it makes major updates to Java SE 6. Java SE 6
APIs are provided for creating irregular, fully transparent, and transparent top-level windows per pixel.

History

Developers of local applications are usually developing the UI
Applications enjoy more advanced flexibility. However, the price for this is to limit the application to a specific platform. In many cases, this flexibility is not as good as obtaining a richer UI.
Close integration of experience and desktop is so important. Traditionally, cross-platform UI toolboxes, such as swing, SWT, QT, and wxWidgets, tend to passively cope with the well-known dilemma. What if only some target platforms support the required functions? In this case, simulating missing features may only make you feel different.

Irregular and transparent windows are cross-platform UIS
The best example of toolbox limitations. If this function is not supported on a specific target platform, there is nothing to do on the platform. This function may be used as a powerful parameter to add this function to the toolbox.
Yes. However, the swing developer community has long argued that major target platforms will soon provide these features. In fact, since Windows 95 (
SeeSetWindowRgnDocumentation. The matching feature in X11 has been available since 1989 (see the X nonrectangular window shape extension library PDF document. In OS X, you can onlyJFrameSet the transparent background color.

Until now, there are three main options for swing applications that are interested in cross-platform transparency and irregular windows.

  • Usejava.awt.RobotCapture the desktop. This method has been reviewed in chapter 41st in the swing hacks book written by Joshua Marinacci and Chris Adamson.
  • Use JNI to package the local API of the target platform.
  • Use the JNA library developed by Timothy Wall. The library was launched in 2007, and Timothy has published a blog on the transparency of irregular windows and letter masks.

The main problem with the first method is to useRobot
Class. Even if you have the permission to get the screen, you must complete it before the display window. In addition, how do I keep the desktop background synchronized? Assume that you are playing YouTube in the background.
Video. Unlike the events generated by the window (Resize and move), AWT does not redraw in any cross window to provide any way to register the listener. Although Chris and
Joshua provides a solution by taking snapshots at least per second, which is not enough for overwriting background video playback. In addition, the window needs to be hidden before each snapshot; this may cause visible flashes.

Using JNI and JNA results in significant visual fidelity improvements. Pure JNI will bring about a sharp reduction in Overhead: You must integrate every related API of the Target Platform
Bind and bind the library. JNA shares this burden with you; it binds the host library and provides class loaders that can extract and load them at runtime. It supports Linux, OS X,
Windows, Solaris, And FreeBSD.

Consumer JRE

Java SE 6 Update N, usually calledConsumer JRESun has made great efforts to reconfigure Java as a feasible way to develop rich desktop applications. The list of new features and major improvements in consumer JRE is quite extensive, and a particularly shining gem is hidden in the release notes of one of the latest week's build code. Bug 6633275 is simply assigned the title "requires support for irregular/transparent windows. However, the possibility of implementing new core JDK functions brings far-reaching significance to swing developers. The rest of this article shows several examples of how to implement and implement this function.

Before further research, there is a very important note. Consumer JRE is officially considered as a secondary update for stable JDK releases. Therefore, no new APIs (classes, methods, and so on) can be added to the "public" package, for examplejava.awtOrjavax.swing. All the APIS discussed in this article arecom.sun.awt.AWTUtilitiesThis class is not officially supported by some APIs. Its position in Java SE 7 is most likely to change, and the signature method may slightly change between the current and the final consumer JRE release. So when this change happens, you are prepared to change your own code.

AWTUtilitiesClass

I will discuss it firstcom.sun.awt.AWTUtilitiesClass, see the transparent and irregular window blog entries in the core Java. First, let's start with the simple window in Figure 1:


Figure 1. Window with controls

To make the window transparent, you can useAWTUtilities.setWindowOpacity(Window, float)Method, as shown in Figure 2:


Figure 2. The same window with 50% opacity

To make the window irregular, you can useAWTUtilities.setWindowShape(Window, Shape)Method, as shown in Figure 3:


Figure 3. Same window, but cropped by an elliptic

As you can see in figure 3, the irregular window does not look very good. The edge of the window is jagged and the overall impression is not very clean. You must useAWTUtilities.setWindowOpaque(Window, boolean)API, and use the flexibility to crop the painting window background. This is illustrated in subsequent swing window flexible cropping and per pixel transparency blog entries. For the upper left corner and upper right corner of the window, this entry adopts the flexible cropping tutorial of Chris Campbell and the reflection tutorial of Romain guy, including the improvement of Sebastien petrucci. Figure 4 shows the transparent flexible cropping window for each pixel:


Figure 4. Flexible cropping and transparent window per pixel

Now we already have these Apis at hand. What are we going to do? The possibility of exploring them is of course another curiosity, and we are planning to look at several examples of mixed diversity.

Tooltip

How can we make the application tool prompt transparent? For lightweight tooltip, it is quite easy to achieve this because they are painted as part of the swing top-level window. (For more information about lightweight pop-up menus, see glass windows and lightweight pop-up menu entries .) However, you must continue to useRobotOr JNI/JNA. Now let's take a look at how to useAWTUtilitiesAPI to complete this task.

Javax. Swing. popupfactory is the factory that creates the pop-up menu. The tooltip is just an example of the pop-up function. Other examples include the drop-down list of the combo box and the menu. The popupfactory. setsharedinstance API can be used to set custom pop-up factory. This is what we want to do. The current pop-up factory is used to create all applications. We will install the custom opacity factory on all tool prompts.

The implementation of the core bullet factory is quite complicated. First, try to create a lightweight pop-up window. When you want to create a heavyweight window, the system needs to manage the cache to reuse the previously created pop-up window. The implementation process will
Create a new heavyweight pop-up window. Running different solutions on a relatively new laptop does not show any outstanding performance breakthroughs. Let's start with the custom bullet Factory:


public class TranslucentPopupFactory extends PopupFactory {
@Override
public Popup getPopup(Component owner, Component contents, int x, int y)
throws IllegalArgumentException {
// A more complete implementation would cache and reuse
// popups
return new TranslucentPopup(owner, contents, x, y);
}
}

TranslucentPopupImplementation is quite simple. The constructor creates a newJWindow, Set the opacity of the tooltip to 0.8, and provide a custom border for drag and drop shadows from the looks project installation:


TranslucentPopup(Component owner, Component contents, int ownerX, int ownerY) {
// create a new heavyweight window
this.popupWindow = new JWindow();
// mark the popup with partial opacity
com.sun.awt.AWTUtilities.setWindowOpacity(popupWindow,
(contents instanceof JToolTip) ? 0.8f : 0.95f);
// determine the popup location
popupWindow.setLocation(ownerX, ownerY);
// add the contents to the popup
popupWindow.getContentPane().add(contents, BorderLayout.CENTER);
contents.invalidate();
JComponent parent = (JComponent) contents.getParent();
// set the shadow border
parent.setBorder(new ShadowPopupBorder());
}

Now we need to rewritePopupOfshow()To mark the entire pop-up window as a transparent style. This requires transparency for each pixel of the drag-and-drop shadow border.


@Override
public void show() {
this.popupWindow.setVisible(true);
this.popupWindow.pack();
// mark the window as non-opaque, so that the
// shadow border pixels take on the per-pixel
// translucency
com.sun.awt.AWTUtilities.setWindowOpaque(this.popupWindow, false);
}

hide()The method is to hide and dispose of the pop-up window:


@Override
public void hide() {
this.popupWindow.setVisible(false);
this.popupWindow.removeAll();
this.popupWindow.dispose();
}

To install the pop-up window, just call


PopupFactory.setSharedInstance(new TranslucentPopupFactory());

Figure 5 shows a sample frame with a transparent tooltip. Note that the consistency on the visual (Transparency and drag-and-drop shadow border) with the tooltip is bound across swing frames and extended to the background eclipse window.


Figure 5. tooltip

Now we make the same animation. When the tooltip is displayed, the color fades out. What if it is hidden? Once you are familiarAWTUtilitiesAPI. Belowshow()Method Code:


@Override
public void show() {
if (this.toFade) {
// mark the popup with 0% opacity
this.currOpacity = 0;
com.sun.awt.AWTUtilities.setWindowOpacity(popupWindow, 0.0f);
}

this.popupWindow.setVisible(true);
this.popupWindow.pack();

// mark the window as non-opaque, so that the
// shadow border pixels take on the per-pixel
// translucency
com.sun.awt.AWTUtilities.setWindowOpaque(this.popupWindow, false);

if (this.toFade) {
// start fading in
this.fadeInTimer = new Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent e) {
currOpacity += 20;
if (currOpacity <= 100) {
com.sun.awt.AWTUtilities.setWindowOpacity(popupWindow,
currOpacity / 100.0f);
// workaround bug 6670649 - should call
// popupWindow.repaint() but that will not repaint the
// panel
popupWindow.getContentPane().repaint();
} else {
currOpacity = 100;
fadeInTimer.stop();
}
}
});
this.fadeInTimer.setRepeats(true);
this.fadeInTimer.start();
}
}

In this case, we marked the window with 0% opacity. Then we start the repetition timer for five iterations. For every fall, we increase the opacity of the window by 20% and re-paint it. Finally, we stop the timer. The final visual result is the smooth fade sequence of the tooltip appearance, which lasts about 250 milliseconds.

hide()The method is very similar:


@Override
public void hide() {
if (this.toFade) {
// cancel fade-in if it's running.
if (this.fadeInTimer.isRunning())
this.fadeInTimer.stop();

// start fading out
this.fadeOutTimer = new Timer(50, new ActionListener() {
public void actionPerformed(ActionEvent e) {
currOpacity -= 10;
if (currOpacity >= 0) {
com.sun.awt.AWTUtilities.setWindowOpacity(popupWindow,
currOpacity / 100.0f);
// workaround bug 6670649 - should call
// popupWindow.repaint() but that will not repaint the
// panel
popupWindow.getContentPane().repaint();
} else {
fadeOutTimer.stop();
popupWindow.setVisible(false);
popupWindow.removeAll();
popupWindow.dispose();
currOpacity = 0;
}
}
});
this.fadeOutTimer.setRepeats(true);
this.fadeOutTimer.start();
} else {
popupWindow.setVisible(false);
popupWindow.removeAll();
popupWindow.dispose();
}
}

First, check whether the fading sequence is still running and delete it as needed. Then, instead of hiding the window immediately, the opacity is changed from 10% to 0 (so the gradient sequence is twice that of the fading sequence) and then hidden and disposed of the pop-up window. Note that the two methods refer to booleantoFadeVariable -- it is settrue. Other types of pop-up windows (menus and the drop-down list of the combo box) do not have fade animations.

Video reflection

Now let's do something more exciting. In the Romain guy blog entry redraw manager demonstration (Chapter 1), it displays the swing component that provides the reflection function. A test application is extracted from his dirty rich client book, co-authored with Chet Haase, showing that the component provides real-time reflection of QuickTime movies. BIND in windowBesidesHow is reflection?

First, there must be a screen for reflecting frames in practical applications. Figure 6 shows the swing frame (using an embedded QuickTime player) that is playing the shape rules of the "get a Mac" advertisement, accompanied by transparent real-time reflection covering the desktop:


Figure 6. Reflection of QuickTime movies

This implementation reused several construction blocks from Romain and extended them to "out-of-memory ". It also has a re-painting Manager (for more information about the re-painting manager, see verify override entries using the re-painting manager) To synchronize the content of the master image with the reflection window. You also need to register the component listener and the window listener on the master region to ensure that the visibility, position, and size of the reflection window and the main window are synchronized. In addition, you also need a custom pane to draw the content to the off-screen buffer. The off-screen buffer is used to draw the main margin and reflection in the reflection window.

Let's take a look at the code. The main class is an extensionJFrameOfJReflectionFrame. The constructor creates a reflection window and adds a non-dual buffering and transparent panel to it. The Panel'spaintComponent()In order to reflect the content of the main painting. After initializing the position and size of the reflected image, we have installed a custom painting manager.


public JReflectionFrame(String title) {
super(title);
reflection = new JWindow();
reflectionPanel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
// paint the reflection of the main window
paintReflection(g);
}
};
// mark the panel as non-double buffered and non-opaque
// to make it translucent.
reflectionPanel.setDoubleBuffered(false);
reflectionPanel.setOpaque(false);

reflection.setLayout(new BorderLayout());
reflection.add(reflectionPanel, BorderLayout.CENTER);

// register listeners - see below
...

// initialize the reflection size and location
reflection.setSize(getSize());
reflection.setLocation(getX(), getY() + getHeight());
reflection.setVisible(true);

// install custom repaint manager to force re-painting
// the reflection when something in the main window is
// repainted
RepaintManager.setCurrentManager(new ReflectionRepaintManager());
}

The following is the listener that keeps the reflection window synchronized with the master listener:


this.addComponentListener(new ComponentAdapter() {
@Override
public void componentHidden(ComponentEvent e) {
reflection.setVisible(false);
}

@Override
public void componentMoved(ComponentEvent e) {
// update the reflection location
reflection.setLocation(getX(), getY() + getHeight());
}

@Override
public void componentResized(ComponentEvent e) {
// update the reflection size and location
reflection.setSize(getWidth(), getHeight());
reflection.setLocation(getX(), getY() + getHeight());
}

@Override
public void componentShown(ComponentEvent e) {
reflection.setVisible(true);

// if the reflection window is opaque, mark
// it as per-pixel translucent
if (com.sun.awt.AWTUtilities.isWindowOpaque(reflection)) {
com.sun.awt.AWTUtilities.setWindowOpaque(reflection, false);
}
}
});

this.addWindowListener(new WindowAdapter() {
@Override
public void windowActivated(WindowEvent e) {
// force showing the reflection window
reflection.setAlwaysOnTop(true);
reflection.setAlwaysOnTop(false);
}
});

The redraw manager is quite simple: it forces the entire root pane of the primary Shard to be repainted, and then updates the reflection window. In this way, we can optimize the synchronization of region reflection updates. This is sufficient for the purpose of the sample application.


private class ReflectionRepaintManager extends RepaintManager {
@Override
public void addDirtyRegion(JComponent c, int x, int y, int w, int h) {
Window win = SwingUtilities.getWindowAncestor(c);
if (win instanceof JReflectionFrame) {
// mark the entire root pane to be repainted
JRootPane rp = ((JReflectionFrame) win).getRootPane();
super.addDirtyRegion(rp, 0, 0, rp.getWidth(), rp.getHeight());

// workaround bug 6670649 - should call reflection.repaint()
// but that will not repaint the panel
reflectionPanel.repaint();
} else {
super.addDirtyRegion(c, x, y, w, h);
}
}
}

The drawing code of the main trim (off-screen buffer) and reflection window is described in detail in the reflection tutorial of Romain.

Conclusion

We have been waiting for this result for a long time, and now we can finally get it done. Although APIs for creating transparent and irregular windows do not yet have officially supported packages, they can still be used to create visual rich cross-platform UIS. The JNA project is displayed from the clear and irregular window (extreme GUI makeover) entries of the Romain blog, which is used to create a visualization competition application with transparent and irregular windows for animation. Now you can use the core JDK for the same processing. This article provides a comprehensive introduction to three examples of displaying the core JDK APIs in practical applications. I'm sure you can come up with more examples.

References
  • Sample Code in this article.
  • Swing painting assembly line Overview
  • About how to use the robot class to simulate transparent windowsChapterPrepared by Joshua Marinacci and Chris AdamsonSwing hacks
  • JNA project compiled by Timothy Wall
  • Introduction to basic APIs for creating transparent and irregular windows in consumer JRE
  • Introduction to creating an irregular window with transparent and flexible cropping per pixel in consumer JRE
  • Tutorial on creating transparent reflection compiled by Romain guy
  • A flexible cropping tutorial written by Chris Campbell
  • Overview of the video reflection component, compiled by Chet Haase and Romain guyDirty rich client.

Kirill grouchnikov started programming software when he was in junior high school. After obtaining a bachelor's degree in computer science, he continued to work in this area. Main areas of interest include desktop applications, imaging algorithms, and advanced UI technologies.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.