Skip to main content

skip to main content

developerWorks  >  Java technology  >

Go state-of-the-art with IFrame

Transform JFrame windows into dazzling application windows

developerWorks
Document options

Document options requiring JavaScript are not displayed

Sample code


Rate this page

Help us improve this content


Level: Intermediate

Michael Abernethy (mabernet@us.ibm.com), IT Specialist, IBM

26 Mar 2004

The IFrame is an application window architecture that allows custom colors, custom borders, custom shapes, custom components, and even transparency. With IFrame, you can get rid of that boring old JFrame you use everywhere in your applications. In this article, IT Specialist Michael Abernethy introduces you to the IFrame class and shows you how you can use it to transform your standard JFrame application windows into state-of-the-art IFrames in no time.

Since the days of Java 1.0, UI developers have been searching for a way to customize their application windows. With the introduction of Swing, the problem was exacerbated, because developers could create the most sophisticated, advanced widgets with an amazing look and feel, but were constrained by the Frame or JFrame that contained it and its OS-specific look. How often have you seen an application that looks good inside the frame's borders, but that the blue Microsoft Windows title bar just doesn't match? Even worse, the application has a 1970s-looking Motif look and feel, but uses the smooth gradient colors of a Microsoft Windows title bar.

Look-and-feel problems with JFrame

These look-and-feel issues, shown in Figure 1, presented many problems to UI developers: The application would look different on every platform because the common look and feel wouldn't apply to the JFrame's properties (title bar colors, borders, shape, and so on) because it's OS-specific.


Figure 1. How looks can change with JFrame
Metal look and feel
Metal Look And Feel
Motif look and feel
Motif Look And Feel
Windows look and feel
Windows Look And Feel

The solution seemed obvious: an OS-independent frame that would let you have all the strengths that a JFrame provided -- registration with the OS window manager, resizing/repainting management, maximizing/minimizing/restore -- but still allowed you to set the look and feel of these components. Java 1.3 provided you the strengths of the JFrame, but sacrificed the customization.

In Java 1.4, Sun introduced a new setUndecorated() function in the Frame class that swung the pendulum back in the opposite direction -- it allowed you to customize everything in a frame, but lacked most of the OS-specific strengths from Java 1.3.

The IFrame class is the long-awaited solution to this problem. By bridging the gap between the two issues, IFrame provides a simple-to-use, yet powerful, solution by allowing you to customize as much or as little of the frame as you need without sacrificing any of the OS-specific functions you've come to expect from JFrame. No longer will you be stuck with the same old blue title bar, the same old three window buttons, and the same old beveled border. While JFrame is still useful for ordinary applications, some applications need more functionality than what it can provide for them, such as:

  • Any application with a custom look and feel
  • Any application used to develop a certain brand image for a company
  • Any application that needs more control over its window

IFrame allows you to go above and beyond the limitations of JFrame by providing an easy-to-use API for producing frames with any shape, title bars that are any color and shape, additional title bar buttons for added functionality, borders of any color and size, components besides buttons and labels on the title bar, and even transparency.

This article introduces you to the IFrame framework. I'll begin by outlining each class and its purpose in the architecture. Of course, the best way to learn how to use IFrame is to learn by example, so I've included four examples of applications made with IFrame, with each example introducing a different level of complexity. After reading this article and learning the IFrame architecture, you should be able to turn your application window from dull (Figure 2) to dazzling (Figure 3).


Figure 2. Before IFrame
JFrame

Figure 3. After IFrame
IFrame1 IFrame2
IFrame3 IFrame4


Back to top


IFrame architecture

The IFrame architecture is very easy and straightforward, as you can see in the class diagram shown in Figure 4. The main class that you will use as your application window is IFrame. An IFrame contains one-to-many instances of the class IBorderPanel, whose subclasses include IWindowTitleBar and the IContentPane. IBorderPanels communicate back with IFrame by firing WindowChangeEvents, which IFrame processes and reacts to.

By examining each of these components in the architecture, it should become clear where and when to override the default functionality so that you can customize your own IFrame.


Figure 4. IFrame architecture
IFrame architecture

IFrame

IFrame is the main class that you will use to create a custom frame. In addition to the methods inherited from IFrame's superclass, JFrame, there are a few public methods added to IFrame that allow you to change some basic look-and-feel components on your frame.

The default IFrame behaves the same as a JFrame does so that a JFrame and default IFrame can be interchangeable. However, by calling some of the public methods available in IFrame, you can quickly change the look of your window with only a few lines of code.

Note: IFrame's getIContentPane() and setIContentPane() methods should be used in place of the JFrame equivalent getContentPane() and setContentPane(). All components that get added to IFrame should call myIFrame.getIContentPane().add(). Adding components to IFrame using getContentPane() or setting the content pane using setContentPane() will lead to unpredictable, and most likely incorrect, behavior.

IBorderComponent

IBorderComponent acts as the superclass to any JPanel that you add to IFrame that has any control over the window's location or resizing. At first glance, the obvious subclasses are IWindowTitleBar and IContentPane, as they appear to be the only two classes doing the resizing and moving. However, there are many examples in current applications where components inside the application window resize or move the application window. For example, all Microsoft Office applications now have a small widget in the lower-right corner of the application window that acts as a resizing mechanism (go ahead and check it out for yourself). So if you design an application that contains all kinds of widgets that resize and move the window, all that is necessary is to subclass IBorderComponent and the widgets will have the same access to moving and resizing that you would get with IWindowTitleBar and IContentPane.

IWindowTitleBar

IWindowTitleBar is where most of the work will take place to customize your frame. Like IFrame, IWindowTitleBar has many public methods that allow you to change the properties of the title bar without the need to subclass it or write the methods yourself. While these methods will allow you to easily make changes to the look and feel, any advanced designs should subclass IWindowTitleBar to get access to paintComponent(), which would allow for more sophisticated title bars. (See Example 3 below for a complex title bar and how it subclasses IWindowTitleBar)

Besides changing the background colors of the title bar, IWindowTitleBar provides many functions that allow you to control IWindowButtons on the title bar. By default, IWindowTitleBar contains the three standard window buttons found in Microsoft Windows applications, but you can easily remove them or add your own additional window buttons that have different functionality altogether. You can change the size and colors of the buttons, and if you create advanced window buttons, you can subclass IWindowButton to paint any shape or color scheme that you want (although changing the look and feel of JButtons is out of the scope of this article).

Perhaps the trickiest part of customizing IWindowTitleBar is managing the borders. By default, the window title bar has a standard rectangular border, but if you create a complex title bar with non-standard borders (see Example 4), you must subclass IWindowTitleBar and manage the borders yourself by overriding isMouseOnBorder() and isInsideTitleBar().

IContentPane

IContentPane mimics the role of contentPane in JFrames by providing the basic container that you will add all your application components to. Because it also subclasses IBorderComponent, it also manages its own borders by default. The default implementation of IContentPane's border is also rectangular. For more complex borders that are not rectangular, you will need to subclass IContentPane and handle the borders yourself by overriding isMouseOnBorder().

IWindowButton

IWindowButton provides a default implementation for the three buttons that appear in standard Microsoft Windows JFrame title bars (minimize, restore, and close), but they also provide a base class for any custom window buttons that you wish to create and add to the title bar. If you wish to add a fourth button to the title bar (if you think you know better than Microsoft), then you would subclass IWindowButton and override paintComponent(). However, lessons for creating custom buttons are not in the scope of this article.

WindowChangeEvent/WindowChangeListener

Swing provides events for nearly everything that can happen to a window. There are approximately 15 events and their respective methods that let you deal with window events. But even with all those events, Swing does not cover every possible event that a window can generate, most noticeably OS-specific events. Finally, with the WindowChangeEvent and WindowChangeListener classes, you can be assured that you are receiving every event that can happen to a window.

WindowChangeEvent handles all instances where a window changes (hence the name of the class). It can change its size, location on the screen, restore state, or minimize/maximize state. Add these five events to the 15 that already exist and you have your bases covered. Nothing can happen to a window now without you knowing about it.



Back to top


Examples

It's time to see for yourself just how powerful IFrame is by writing a few lines of code and changing the entire look of the application window. Remember, IFrame can be as simple or as complex as you need it to be.

In this section, I'll run through four examples that outline all the basics you should need to get started with IFrame. By reading these and running them on your own machine, you'll see what you couldn't really envision by just reading the explanations or the API. By running all four examples and examining the code that produced each, I think you'll understand how IFrame can become a powerful tool in your applications.

All the examples are contained in the com.ibm.iwt.examples package, available for download in Resources, and all of them have a main() method you can run. They are written using JDK 1.4.

Example 1: Default IFrame

To keep IFrame "backwards compatible," I made the default implementation of IFrame look exactly like a JFrame would look, as shown in Figure 5:


Figure 5. Default IFrame
Example 1

Because IFrame doesn't get its information from the native OS, I had to choose one to mimic. The default IFrame implementation looks like how the JFrame does on Microsoft Windows 2000, so we'll go with that. If you are running applications on a Windows 2000 machine, you should be able to interchange JFrame and IFrame without noticing any difference. If you're not on Windows 2000 -- well, your first practice application can be mimicking your OS. Listing 1 shows you how easy it is to create an IFrame:


Listing 1. IFrame example 1
  public TestApp1()
  {
    setTitle("Window");
  }

Yeah, it's that easy (and imagine if all application development were).

Suggested uses: If you'd like backwards compatibility with a JFrame.

Example 2: Changing the default colors, borders, and sizes

Now to get to some more exciting code. In this example, I changed the background color of the title bar and the borders around the frame to red, changed the colors of the window buttons, and also changed the size of the title bar and the window buttons. Figure 6 shows you the IFrame you can create in Example 2.


Figure 6. Changing colors, borders, and sizes
Example 2

Just from this description of changes, you should see that all of these changes would be impossible in a JFrame, but with IFrame it can be done easily. Listing 2 shows you how to create the IFrame used in Example 2:


Listing 2. IFrame example 2
  public TestApp2()
  {
    IWTUtilities.setBorderSize(new Insets(3,3,3,3));
    setIContentPaneBorder(new LineBorder(Color.red, 3));
    setTitleBarHeight(35);
    setTitleBarBackground(Color.red);
    setTitleBarButtonColors(Color.red, Color.white);
    setTitleBarButtonSize(new Dimension(26, 26));
    setTitle("Window");
  }

That's it. That's all it takes to change your frame's look and feel. Although this is the basic example of IFrame, using only six lines of code, we've accomplished something that UI developers have been trying to do for years. This basic example is already more advanced than 99 percent of the application windows currently out there.

Suggested uses: If you'd like to quickly change the look and feel of the frame without changing it from the OS-specific frame too drastically.

Example 3: Utilizing subclasses of IWindowTitleBar

If you want to move beyond the basic changes of color, size, and buttons on the title bar, you'll have to subclass the IWindowTitleBar class to take full advantage of everything you can possibly do. When you create your subclass, you have a whole new set of possibilities for your title bar, including more advanced painting options and, most powerfully, the ability to add any components you wish to the title bar. Why feel constrained by buttons and labels on the title bar? Add that JTable you've always wanted to add. Simply call setTitleBar() in IFrame and you can create a subclass that is the most advanced title bar in the history of application development and use it in whatever IFrame you'd like. Figure 7 scratches the surface of what is possible when it comes to creating custom window components:


Figure 7. Creating custom window components
Example 3

In this example, I took full advantage of all these new abilities by building off the frame in Listing 2, and replacing that boring static red title bar with a new, dynamic one. As you can see in the picture, the title has been moved from the left side to the middle with a more readable font. I've replaced those three standard buttons on the right side with a single Close button on the left side. Finally, and perhaps most originally, I've added a JSlider to the right side of the title bar that allows the user of this particular IFrame to dynamically change the gradient color of the background of the title bar. The code snippet in Listing 3 shows you the additional code needed to transform Example 2 to Example 3. This would have been impossible in a JFrame.


Listing 3. IFrame example 3
  public TestApp3()
  {
    IWTUtilities.setBorderSize(new Insets(3,3,3,3));
    getIContentPane().setBorder(new LineBorder(Color.red, 3));
    setTitleBar(new TitleBar());
  }

  private class TitleBar extends IWindowTitleBar implements ChangeListener
  {
    private Color c = new Color(0,0,0);
    private JSlider slider;

    public TitleBar()
    {
      setPreferredSize(new Dimension(0, 26));
      removeWindowDecorations();
      addWindowButton(IWindowButton.CLOSE, SwingConstants.LEFT);
      setWindowButtonColors(Color.RED, Color.WHITE);
      addTitle(getTitle(), SwingConstants.CENTER, new Font("Verdana", Font.BOLD, 14), Color.WHITE);
      slider = new JSlider();
      add(slider, new GroupFlowLayoutConstraints(SwingConstants.RIGHT, new Insets(3,3,3,3)));
      slider.addChangeListener(this);
      slider.setMaximum(255);
      slider.setMinimum(0);
      slider.setOpaque(false);
    }

    public void paintComponent(Graphics g)
    {
      super.paintComponent(g);
      PaintUtilities.paintGradient(g, 0, 0, getWidth(), getHeight(), c, Color.WHITE, 
      SwingConstants.HORIZONTAL);
    }

    public void stateChanged(ChangeEvent e)
    {
      c = new Color(slider.getValue(), 0, 0);
      repaint();
    }
  }

By looking at the code to create this IFrame, you can see it's no more complex than the code in Listing 2. However, I moved all the code into the subclass of IWindowTitleBar for two reasons:

  • To provide more sophisticated-looking title bars by overriding paintComponent() in IWindowTitleBar
  • To include the JSlider that dynamically changes the background color of the title bar

You can let your imagination run wild when it comes to creating new widgets for the title bar now that you can add any JComponent in any location. The JSlider changing the background color is just the tip of the iceberg when it comes to creating new functionality residing on the title bar. There are probably many ingenious custom components just waiting to be developed for use on the title bar.

Suggested uses: Some instances when it would be a good idea to use a subclass of IWindowTitleBar would be if:

  • You would like to create more advanced graphics on the title bar, instead of a single solid color
  • You are often dynamically changing the title bar properties of the frame and don't wish to call multiple functions every time they have to change
  • You wish to add other components to the title bar besides the default ones

Example 4: Bringing it all together with transparency

The last example brings all the other examples together and adds the newest addition to IFrame -- transparency. This example is the most advanced and is a great example of the power of IFrame to create a great-looking application window with a minimal amount of effort. Figure 8 shows you a sophisticated application window that uses a small amount of transparency to set it apart from other application windows.


Figure 8. Adding transparency
Example 4

First, let's talk about the transparency. A couple of years ago, Microsoft Windows applications started to have frames that weren't the standard rectangular shape. Windows Media Player was one of the first widespread examples of this and since it came out, it has become rather trendy and cool to have an application that isn't rectangular. Well, Java applications have never had this capability and have always had a hard time with transparency, especially when interacting with natively drawn pixels.

Fortunately, IFrame fixes all that and allows you to develop application windows that do have transparency, even transparent to natively drawn pixels. setTransparent() in IFrame draws the specified component transparent at the specified bounds. In most cases, the component will either be a subclass of IWindowTitleBar or a subclass of IContentPane. The call to setTransparent() should be in the subclass's paintComponent() in order for it to repaint correctly with the correct pixels underneath it.

As a final word of caution, painting transparency is relatively slow, and you should keep your transparent regions relatively small.

This final example introduces some other more advanced abilities of IFrame. As you can see in Figure 8, the title bar is no longer the standard rectangular title bar. It is a custom designed shape, with completely different borders than a rectangle would have. Thus, in the subclass of IWindowTitleBar that I have created, I had to override the isMouseOnBorder() and isInsideTitleBar() methods so that the title bar will behave correctly when drawing cursors and allowing for resizing. Listing 4 shows you the code needed to produce the application window seen in Example 4.


Listing 4. IFrame example 4
  public TestApp4()
  {
    setTitle("Window");
    IWTUtilities.setBorderSize(new Insets(0,7,7,7));
    IWTUtilities.setDiagonalSize(20);
    getIContentPane().setBorder(new AppBorder());
    getIContentPane().setBackground(new Color(255, 255, 102));
    setTitleBar(new TitlePanel());
  }

  private class TitlePanel extends IWindowTitleBar
  {
    public TitlePanel()
    {
      setPreferredSize(new Dimension(800,35));
      setFont(new Font("Verdana", Font.BOLD, 22));
      removeWindowDecorations();
    }

    protected boolean isInsideTitleBar(int x, int y)
    {
      if (x < (int)getWidth()*.1 || x > (int)getWidth()*.9)
        return false;
      return true;
    }

    protected void isMouseOnBorder(int x, int y)
    {
      if (y > 10 && y > 16 && !isInsideTitleBar(x, y))
        isMouseOnBorder = true;
      else
        isMouseOnBorder = false;
    }

    public void paintComponent(Graphics g)
    {
      super.paintComponent(g);

      // ... paint code here

      setTransparent(this, g, 0, 0, w+1, 10);

      PaintUtilities.paintDropShadow(g, (int)(w*.1), 0, (int)(w*.8), 27);
      Color c1 = new Color(67, 118, 135);
      Color c2 = new Color(105, 152, 199);
      PaintUtilities.paintGradient(g, (int)(w*.1), 0, (int)(w*.9), 14, c1, c2);
      PaintUtilities.paintGradient(g, (int)(w*.1), 14, (int)(w*.9), 13, c2, c1);

      Graphics2D g2 = (Graphics2D)g;
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
      g.setColor(Color.white);
      int strW = SwingUtilities.computeStringWidth(g.getFontMetrics(), getTitle());
      int strH = g.getFontMetrics().getMaxAscent();
      g2.drawString(getTitle(), w/2-strW/2, h-strH/2);
      g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_OFF);
    }

    private void drawBorder(Graphics g, int x, int y, int w, int h)
    {
      g.drawLine(x, 10+y, x, h);
      g.drawLine(x, 10+y, w-x, 10+y);
      g.drawLine(w-x, 10+y, w-x, h);
    }
  }

  private class AppBorder extends AbstractBorder
  {
    public void paintBorder(Component c, Graphics g, int x, int y, int width, int height)
    {
      // ... paint border
    }
  }

Suggested uses: Creating a frame that is not completely rectangular is the current trendy thing to do in UI development (look no further than Windows XP). With IFrame, your Java application won't be left behind. By using transparency and overriding IWindowTitleBar and all its advanced functions, you can create a highly sophisticated-looking frame that you can use as the default frame for entire corporate applications. The advanced functionality allows a UI developer to develop a frame that users will automatically associate with a certain company (instead of being stuck with a frame that users will automatically associate with a certain company in Redmond, Washington).



Back to top


Conclusion

IFrame finally bridges the gap that existed in Java development by allowing a UI developer to have complete control over both the functionality and look of their frames. It allows UI developers to create a simple IFrame that merely changes the font of the title bar or create a complex IFrame that changes the entire look of a corporation. The power of IFrame lies in its ease of use for the developer. It provides all the functionality a developer needs to create changes to the frame, but also is extremely extendable and allows the developer to change only what he needs without disrupting the rest of the default behavior.

As you can see from all the examples that I've done, your imagination is the limit as far as the possible looks of frames is concerned. I'm sure that as you've read this you've had ideas pop into your head, and I hope that after reading this article you can quickly get them from your head to the screen using IFrame.

I'm very interested to see what kinds of IFrames you develop, so please send me screenshots of any IFrames you come up with. I'm curious to see just how "out of the box" someone can take the IFrame.




Back to top


Download

DescriptionNameSizeDownload method
IFrame source codej-iframe.zip28KBHTTP
Information about download methods


Resources



About the author

Michael Abernethy works with the IBM WebSphere Services team based in Austin, Texas. He provides WebSphere solutions to an On-Demand world.




Rate this page


Please take a moment to complete this form to help us better serve you.



 


 


Not
useful
Extremely
useful
 


Share this....

digg Digg this story del.icio.us del.icio.us Slashdot Slashdot it!



Back to top