Welcome

Welcome to my personal blogs, here you can find interesting stuffs I did with Java, Mac and DoTA AllStars. For Java developer or just Java student, you can request for an article guide. Due to recently most of my projects based on Swing technology, I only accept guide request about Swing and Java Graphics. My Mac guides section aimed for Mac development environment, you won’t find general Mac guides here.

If you have similar interest with me on music and movies, you can check out my music and movies section, and we can share news or anything related to my interest.

Enjoy.


wise man said:
“Java user interface could make .NET looks like CDE Look And Feel”

1 comment November 1, 2008

Hi… I’m back

Thanks for everyone visited my blog site… Sorry I didn’t update my blog on the last 12 months… Let just say that I have some bad time recently.

But now I’m back and hope you guys like the new theme. Here are my plans till the end of 2009 with this blog:

  • Some iPhone tutorials
  • Snow Leopard Java LaF tutorials
  • Painter API (enhancement from SwingX) for Java Swing
  • DoTA Allstars Handbook App (Desktop & iPhone)

Hope u guys like it!

Add comment September 25, 2009

How To : GradientPaint

JVoD Lobby Panel

JVoD Lobby Panel

There are plenty reason you may have why you want your Java application looks pretty cool. One of the best statement probably to give nice impression for the user itself. As we know, SUN started to improve Java desktop user interface as their movement to increase their market share on desktop and mobile platform. Actually, the old Java Graphics engine already provide many ways to create fully nice looking application since JDK 1.1 as Java 2D API introduced and keep update till right now JDK 6 update 10. Right now, as the competition on VM getting hot, SUN move to provide the developer even easier implementation on Swing user interface improvement started from JSR 295 and JSR 296.

JVoD Browse Movie Panel

JVoD Browse Movie Panel

To build cool apps you need nice looking effect with a bit good sense of design taste. You can work on your taste yourself, I’ll help with the code!

GRADIENT PAINT

I’m sure you already know what it’s mean. The problem is how to draw a nice gradient effect with Java not Photoshop! First of all, let me introduce to you GradientPaint class as part of java.awt package. Let’s take a look!

GradientPaint(float x1, float y1, Color color1, float x2, float y2, Color color2)

Let’s break the constructor:

  • x1, start x point
  • y1, start y point
  • color1, start color drawing start from (x1,y1)
  • x2, end x point
  • y2, end y point
  • color2, end color drawing at (x2, y2)

There are also an option to draw with cyclic method. I’ll tell you more about cyclic method later.

Before we create a gradient effect you should decide what kind of gradient effect you want to create. It’s good to know there are 4 options to draw gradient effect:

  • Horizontal gradient,
  • Vertical gradient,
  • Reflected horizontal gradient,
  • Reflected vertical gradient.

HORIZONTAL GRADIENT

horizontal gradient paint demo

horizontal gradient paint demo

To create horizontal gradient we can simply define x1, x2 and colors parameters. First, the idea of horizontal gradient is to paint first color degrade to second color from x1 to x2. Why we don’t bother about y1 and y2 parameters? We can simply put 0 value into those parameters to create horizontal gradient, that’s mean Graphics should draw repeatedly from y – 0 into y = height of the component. What if we want to draw only half of the component height with horizontal gradient? For instance, assume the component height is 400px and we only want to fill the first 200px with our gradient paint, then all you have to do is fill y1 =0 and y2 = 200 or y2 = getHeight() / 2 and vice versa for vertical gradient paint.

Now, you already got the math idea, let’s implement it on code!

            @Override
            protected void paintComponent(Graphics g){
                Graphics2D g2 = (Graphics2D)g.create();

                Paint p = new GradientPaint(
                        0, 0, new Color(0x7D838F),
                        getWidth(), 0, new Color(0x272B39)
                    );
                g2.setPaint(p);
                g2.fillRect(0, 0, getWidth(), getHeight());

                g2.dispose();
            }

First step you create Graphics2D instance from provided Graphics instance by duplicating it. Then you need to create GradientPaint instance with x1 = 0, y1 = 0, color1 = new Color(0×7D838F) means first color draw start from top left component. The end point defined as x2 = getWidth(), y2 =0, color2 = new Color(0×272B39) means gradient paint will draw fill the component horizontally. Then you set Graphics2D instance g2 to our defined painting method by calling setPaint() method and pass the GradientPaint instance. The last thing to do is invoke fillRect() method then dispose Graphics2D instance because we already done with our custom code, runtime doesn’t need it anymore.

VERTICAL GRADIENT

Vertical Gradient Paint

Vertical Gradient Paint

You already know how to paint horizontal gradient, so let’s direct to the vertical gradient idea. Basically it’s a reverse from horizontal gradient, if we worked with x1 and x2 parameters on horizontal gradient, then ignore it for vertical gradient! We’ll be working with y1 and y2 parameters here. Before, we defined x2 = getWidth(), then now define y2 = getHeight().

Let’s see the code implementation!

            @Override
            protected void paintComponent(Graphics g){
                Graphics2D g2 = (Graphics2D)g.create();

                Paint p = new GradientPaint(
                        0, 0, new Color(0x7D838F),
                        0, getHeight(), new Color(0x272B39)
                    );
                g2.setPaint(p);
                g2.fillRect(0, 0, getWidth(), getHeight());

                g2.dispose();
            }

The code above will draw gradient effect vertically from top to bottom with defined colors degradation. Isn’t that simple? Yes it is, so have fun changing the code.

REFLECTED HORIZONTAL GRADIENT

Reflected Horizontal Gradient

Reflected Horizontal Gradient

If you have experience using gradient effect on Photoshop you’ll notice that there is an option to create the gradient effect to be draw reflected. Well, on Java there are three ways to achieve this, let’s take a look on the options!

  1. Draw two gradient paint with half of the component size each,
  2. Fill the component twice with the same gradient paint each cover half of the component area,
  3. Or define gradient paint to cover half of the component area and pass true on cyclic option.

First and second options are not the best way! Why? We can do the math to determine half area of the component and sequentially fill the area twice or create two gradient paint instance, but to code aesthetically, we need to simplify the code as much as we can. And we actually can! Java already provide the second constructor on GradientPaint class with cyclic option, let’s take a look!
GradientPaint(float x1, float y1, Color color1, float x2, float y2, Color color2, boolean cyclic)
Just look on the last parameter. Cyclic means drawing will be done repeatedly between defined two colors. Human version of this statement is if we create GradientPaint instance to cover only partial of the component’s area, then if it’s true, drawing will be repeat with the reverse painting colors to cover the rest of the un-covered area. If we defined GradientPaint instance to cover the whole area, then it simply will be ignored. Why? No more room to draw the cyclic paint! If you already got the idea, then let’s try modify our code!

            @Override
            protected void paintComponent(Graphics g){
                Graphics2D g2 = (Graphics2D)g.create();

                Paint p = new GradientPaint(
                        0, 0, new Color(0x7D838F),
                        getWidth(), 0, new Color(0x272B39),
                        true
                    );
                g2.setPaint(p);
                g2.fillRect(0, 0, getWidth(), getHeight());

                g2.dispose();
            }

It’s quite simple, just add another parameter to the constructor with true value on cyclic option and modify x2 parameter into x2 = getWidth()/2. Now, it will draw gradient paint reflected horizontally on the component with each cover the half area. You can even create multiple gradient cyclic by make the paint area smaller like x2 = getWidth() / 4.

REFLECTED VERTICAL GRADIENT

Reflected Vertical Gradient

Reflected Vertical Gradient

Same idea like vertical gradient above, just modify the y2 parameter into y2 = getHeight() / 2 or any value you want and pass true on cyclic option.

FAQ

1. How about the performance ?
Solution : On most current modern machine it will take less than 50ms to draw one gradient paint, so no need to worry about this, as long as you do it right with memory management, then you won’t event feel the glitch!

2. What’s the different with working on GradientPaint parameters compare to fillRect() method ?
Solution : When working with GradientPaint parameters and you cover partial area, the rest will be fill with the last color. On fill() method, the rest will be draw using component’s background color as defined by L&F or yourself.

3. Can Java draw gradient effect into different shape than just ‘old school’ rectangle ?
Solution : Yes you can! There are no limitation on what shape Java can draw. Just do the math and use AffineTransform to transform your shape into any kind of shape! To use basic shape, use fill() method variant or use basic Shape instance like RoundRectangle2D and Ellipse2D. Take a tour to java.awt.geom package and read the documentation.

4. How to create mutiple colors with multiple points on GradientPaint ?
Solution : There are two options, you can draw multiple GradientPaint instance or do the math on fill() method. For JDK 6, you can use LinearGradientPaint instance or for JDK 5 you can download Apache Batik multiple gradient paint API (this API is the same API used on JDK 6 to draw multi stop gradient paint). I’ll write the guide how to use this class soon!

5. Can Java create color degradation from or into transparent color ?

Translucent Gradient Paint

Translucent Gradient Paint

Solution : Yes you can! As long as you defined the component background color through setBackground() method into new Color(0,0,0,0) and defined the gradient paint color from or into that color, you can achieve transparent color degradation. Amazing isn’t it ? Worth the try!

6. What does it means with new Color(0×7D838F) ? Is there any other human readable form ?
Solution : Color instance have several constructor options to define the color value, I prefer to use Hex value on parameter (sorry for that). There are other options, if you familiar with standard RGB color value definition, you can use it like for gray color would be new Color(66,66,66) and so on. You can even use alpha value like I described on point 5 to determine alpha color value. Actually 0×7D838F is the same value as integer 8225679, so result color is quite same, the different just the accuracy of the color range. You can use Apple Digital Color Meter or Adobe Photoshop color chooser to determine RGB value into hex, actual or percentage value both for 8 and 16 bit integer value.

7. I don’t like the math part ! What should I do ?
Solution : Dude, why don’t you just learn it a little bit… It’s worth the effort, trust me! I don’t like numerical methods and algebra classes either, but when it comes into image processing programming, you’ll need it much than you ever thought. The other guides I’ll write will cover more maths than this, so, you better start to like it.

If you have questions or better implementation code than mine here, don’t hesitate to leave comment/s. Hope this guide can help you finding your path to become Java developer.

2 comments November 3, 2008

Translucent Custom Shape Window

Have you ever wonder with most Mac applications provide translucent round rectangle window? Or you already seen JavaFX sample applications with fancy translucent gradient effect on their Frame?

If not, take a look on this sample image taken from Apple iPhoto apps:

iphoto sample palette window

iphoto sample palette window

Same window style also applied for Mac OS X Leopard QuickLook window. It’s give better user interface experience if we use it with the right purpose. Keep in mind to not using all this kind of window on entire application’s windows. Use it more as popup menu or control dialog that only activated when user wants it to appear. Right now as JDK 6 update 10 finnaly release, actually we can create a translucent JRootPane on top level container as introduced by Apple JDK 6 couples month before through client property.

Then what about user that actually doesn’t really want to download new JDK and keep stick with their old JDK 5 or recent JDK 6 version? Most users wants their application to just able to run without any other efforts (that’s made Mac more popular than other *NIX OS for end user) and not much end user hook up with Java application (native application more preferable).

Enough talking, let’s try to create custom shape translucent window using JDK 5 or JDK 6.

Key Idea :

  1. every container has a content pane including top level container such as JFrame or JDialog,
  2. create a custom content pane and override it’s paintComponent() method,
  3. provide custom shape, on this sample we’re using RoundRectangle2D.Float class,
  4. set composite using AlphaComposite instance for translucent effect,
  5. set painting color to black,
  6. fill the shape,
  7. create title pane with gradient effect background and create re-size corner image for drag point where user can stretch the window.

With those concepts try to imagine what the result would be on your mind.

Done? Assume you already imagine the result, is it same as the sample pictures above? Let’s break the code!

STEP 1

Let’s open your IDE and create a new class call as FancyWindow as JDialog extension with two constructor methods, it would be something like this:

import java.awt.Frame;
import javax.swing.JDialog;
import javax.swing.JComponent;

public class FancyWindow extends JDialog{
    private JComponent fcontentPane, contentPane, titlePane, bottomPane;

	public FancyWindow(Frame parent){
		this(parent, "");
	}

	public FancyWindow(Frame parent, String title){
		super(parent, title);
	}
}

STEP 2

To create a custom content pane for the entire dialog, we use fcontentPane instance, for better looking code, create a method or nested class to generate our content pane (demo shown using method).

private JComponent createContentPane(){
	return new JComponent(){
		@Override
		protected void paintComponent(Graphics g){
			//TODO your custom painting code here
		}
	};
}

STEP 3

Now let’s fill the blank! Keep in mind, once we override paintComponent() method Java Runtime expected we handle painting issues for this component. Based on that fact, never leave the block code blank, let’s learn about the method parameter Graphics.

Every Swing or AWT component has it’s own Graphics instance generated by Java Runtime. Is that good? Of course, it simplify our task, we never know how to render the component natively on host operating system. Is the heavy lifting done by runtime? Not really, now we need to provide runtime how to render the component with the language that Java understand, the rest, let Java decide how to make it possible on host operating system. In our case, we’re going to use AWT classes. Why AWT not Swing? Because Swing based on AWT and back to basic, Swing provided to create pure Java component with consistent rendering on every operating system, while AWT itself provide native operating system user interface rendering. To simplify the statement, AWT handle all Event Dispatch Thread related with user interface component directly with host operating system, and that’s including Swing rendering process. Swing never know how to render component for host operating system but AWT did. You can read Graphics Fundamental chapter on Filthy Rich Client book, it’s a great book, worth every penny!

What’s the different between Graphics & Graphics2D? Graphics and Graphics2D are the same thing but provide different capablities to draw on the screen. Graphics is old school but stay cool, Graphics2D is freaking awesome (make .NET user interface looks like CDE L&F). Which one we should use? Both are needed, depend on the case. We’ll see in the next step.

Let’s create Graphics2D instance from provided Graphics instance by adding:

Graphics2D g2 = (Graphics2D)g.create();

Why duplicating provided Graphics instance? Runtime still need Graphics instance even if you’re already done with your custom painting, and once you cast Graphics to Graphics2D, actually you’re going to modified the same instance, means any changes you made on Graphics2D instance will manipulate directly to the Graphics instance used by runtime. Meanwhile, runtime doesn’t need Graphics2D instance to do the modification once you’ve done, so to avoiding spamming memory space, you need to dispose Graphics2D instance at the end of your custom painting code. If you just cast directly Graphics instance without duplicating it, the provided Graphics instance will be dispose too when you call dispose() method from Graphics2D instance, resulting empty painting when the component render on the screen.

Let’s create the shape! Java provide many ways to draw custom shape. You can transform the rectangle shape into almost any shape by using AffineTransform class, or just using basic shape already provided. Take a tour into java.awt.geom documentation. On this sample, we’re going to use RoundRectangle2D.Float instance to provide shape. Take a look on the constructor method.

Shape s = new RoundRectangle2D.Float(
          0, 0,
          getWidth(), getHeight(),
          16, 16);

First two parameters defined starting point from which coordinate you’re going to draw the shape, on our case full window size meaning x=0 and y=0. Second two parameters defined end point drawing coordinate achieve by calling getWidth() and getHeight() methods. The last two parameters defined width and height corner round arch to create rounded rectangle shape.

STEP 4

Set the content pane translucent value by using AlphaComposite instance. There are two different ways to achieve this depending on which JDK version you use.

For JDK 5 use:

Composite old = g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f));

For JDK 6 you can use above way or this one:

Composite old = g2.getComposite();
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER).derive(0.75f));

Why store the old composite value? We’re going to need it to render child components unless you want child components added to the container rendered translucent too. What the AlphaComposite.SRC_OVER means? Don’t bother about that, i’m not gonna described it, you can read the documentation about other alpha rule Java supported. But, like Chet Haase and Romain Guy said “We only use one : SRC_OVER”.

STEP 5

What color you want to use? Keep in mind that never ever use R/G/B/C/M defined colors, means never use red color as (255,0,0) or blue as (0,0,255) value. It make your user’s eyes sick. Use soft colors like pastel or crayon colors or simply use Apple Digital Color Meter (built-in on every OS X) to ’steal’ the color value from other cool applications. In our case we’re going to use plain black color as background color by adding:

g2.setColor(Color.BLACK);

STEP 6

We already create Graphics2D instance, rounded rectangle shape and set the render background color for the shape, now it’s time to draw the shape. We want the entire shape render with black color that’s why we’re going to use fill() method rather than draw(). draw() method only use to draw line based on the defined stroke strength. Why not use fillRoundRect() method from the Graphics instance? Because we want the component render as round rectangle not round rectangle inside the rectangle. Confused? Try it yourself! Specially on button component, if we provide the shape instead of define it through fillRoundRect() method, the component will be draw entirely like shape we provided, otherwise the original shape from the component will be still render.

Now add the following code:

g2.fill(shape);

STEP 7

Now create a title and bottom components render the title, close button and re-size corner. Assume that you already create necessary images and components, the only problem is how to install mouse listener to move the window. I got this idea from MetalRootPaneUI source code on Metal Look & Feel package. You can see full code section to create mouse input listener to move the window when titlePane being drag. NOTE: I have no idea how to resize the window when resize corner being drag without making lag scenes, so, let’s it become your homework, don’t forget to let me know if you can make it happen!

Now you already complete the entire code, let’s give it a try! The window should appears like this one:

decorated version of FancyDialog

default version of FancyDialog

What’s wrong? We forget set the dialog to be undecorated. Add the following code to the constructor:

setUndecorated(true);

Now it’s gonna look like this:

undecorated version of FancyDialog

undecorated version of FancyDialog

Take a look at the edges, you’ll find white background still rendered, and that’s what made the dialog not translucent. What we have to do? This part is tricky, I never found it on any guides, but when I read entire Aerith source code I found out that Color instance can have alpha value. When we set it to 0,  the color will be transparent not black. To make it happen place this simple code:

setBackground(new Color(0,0,0,0));

I did some pimped code to make it even more better looking by using LinearGradientPaint from Apache Batik project or java.awt.LinearGradientPaint on JDK 6. The library for JDK 5 can downloaded through the project site or from SwingX library. Now it’s looks like this:

pimped version of FancyDialog

pimped version of FancyDialog

It’s translucent window, try it yourself. For references, here is my full code written in JDK 6 code style, the different just in GroupLayout methods and LinearGradientPaint:

import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Dialog;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.LinearGradientPaint;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Window;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.geom.RoundRectangle2D;
import javax.swing.GroupLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.event.MouseInputListener;

public class FancyWindow extends JDialog{
	private JComponent titlePane, contentPane, bottomPane;
	private JLabel titleLabel, resizeLabel;
	private JButton closeButton;
	private Window w = this;
	private ActionListener closeListener;

	public FancyWindow(Frame parent){
		this(parent, "");
	}

	public FancyWindow(Frame parent, String title){
		super(parent, title);
		setUndecorated(true);
		setResizable(false);
		setBackground(new Color(0,0,0,0));
		setContentPane(createContentPane());
		initComponents();
		setSize(200, 300);
		setLocationRelativeTo(parent);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void setTitle(String title){
		titleLabel.setText(title);
	}

	/**
	 * Install window closing listener when close button pressed.
	 * @param listener desired action to take.
	 */
	public void installCloseButtonListener(ActionListener listener){
		if(closeListener != null){
			closeButton.removeActionListener(closeListener);
		}

		closeListener = listener;
		closeButton.addActionListener(closeListener);
	}

	private void initComponents(){
		titleLabel = new JLabel(getTitle());
		titleLabel.setForeground(Color.WHITE);
		closeButton = new JButton();
		closeButton.setIcon(new ImageIcon(FancyWindow.class.getResource(
				"close.png")));
		closeButton.setRolloverIcon(new ImageIcon(FancyWindow.class.getResource(
				"close_hover.png")));
		closeButton.setPressedIcon(new ImageIcon(FancyWindow.class.getResource(
				"close_pressed.png")));
		closeButton.setFocusable(false);
		closeButton.setFocusPainted(false);
		closeButton.setBorderPainted(false);
		closeButton.setContentAreaFilled(false);
		titlePane = createTitlePane();
		resizeLabel = new JLabel(new ImageIcon(FancyWindow.class.getResource(
			"resize_corner_dark.png")));
		bottomPane = createBottomPane();

		setLayout(new BorderLayout());
		add(titlePane, BorderLayout.NORTH);
		add(contentPane, BorderLayout.CENTER);
		add(bottomPane, BorderLayout.SOUTH);

		MouseInputHandler handler = new MouseInputHandler();
		titlePane.addMouseListener(handler);
		titlePane.addMouseMotionListener(handler);
	}

	private JComponent createBottomPane(){
		JComponent result = new JComponent(){};
		result.setLayout(new FlowLayout(FlowLayout.RIGHT));
		result.add(resizeLabel);

		return result;
	}

	private JComponent createTitlePane(){
		JComponent result = new JComponent(){
			protected void paintComponent(Graphics g){
				setOpaque(false);
				Graphics2D g2 = (Graphics2D)g.create();
				g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
				Composite old = g2.getComposite();
				g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f));

				LinearGradientPaint paint = new LinearGradientPaint(0, 0, 0, getHeight(),
						new float[] {.0f, .499f, .5f, 1.0f},
						new Color[] {new Color(0x858585),
							new Color(0x3c3c3c),
							new Color(0x2c2c2c),
							new Color(0x333334)});
				g2.setPaint(paint);
				Shape shape = new RoundRectangle2D.Float(0,0,getWidth(), getHeight(), 16, 16);
				g2.fill(shape);
				g2.setComposite(old);
				g2.dispose();
			}
		};

		GroupLayout layout = new GroupLayout(result);
		result.setLayout(layout);
		layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
				.addGroup(layout.createSequentialGroup()
						.addGap(2)
						.addComponent(closeButton)
						.addPreferredGap(ComponentPlacement.UNRELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addComponent(titleLabel)
						.addPreferredGap(ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
						.addGap(2)
				)
		);
		layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
				.addGroup(layout.createSequentialGroup()
						.addGroup(layout.createParallelGroup(GroupLayout.Alignment.CENTER)
								.addComponent(titleLabel)
								.addComponent(closeButton)
						)
				)
		);

		return result;
	}

	private JComponent createContentPane(){
		return new JComponent(){
			@Override
			protected void paintComponent(Graphics g){
				Graphics2D g2 = (Graphics2D)g.create();
				g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
				Composite old = g2.getComposite();
				g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f));
				g2.setColor(Color.BLACK);
				Shape shape = new RoundRectangle2D.Float(0, 0, getWidth(), getHeight(), 16, 16);
				g2.fill(shape);
				g2.setComposite(old);
				g2.dispose();
			}
		};
	}

	/**
	 * Class handling mouse input to enable titlePane become drag-able and window become move-able.
	 */
	private class MouseInputHandler implements MouseInputListener {
        private boolean isMovingWindow;
        private int dragOffsetX;
        private int dragOffsetY;
        private static final int BORDER_DRAG_THICKNESS = 5;

        public void mousePressed(MouseEvent ev) {
            Point dragWindowOffset = ev.getPoint();
            if (w != null) {
                w.toFront();
            }
            Point convertedDragWindowOffset = SwingUtilities.convertPoint(
                           w, dragWindowOffset, titlePane);

            Frame f = null;
            Dialog d = null;

            if (w instanceof Frame) {
                f = (Frame)w;
            } else if (w instanceof Dialog) {
                d = (Dialog)w;
            }

            int frameState = (f != null) ? f.getExtendedState() : 0;

            if (titlePane.contains(convertedDragWindowOffset)) {
                if ((f != null && ((frameState & Frame.MAXIMIZED_BOTH) == 0)
                        || (d != null))
                        && dragWindowOffset.y >= BORDER_DRAG_THICKNESS
                        && dragWindowOffset.x >= BORDER_DRAG_THICKNESS
                        && dragWindowOffset.x < w.getWidth()
                            - BORDER_DRAG_THICKNESS) {
                    isMovingWindow = true;
                    dragOffsetX = dragWindowOffset.x;
                    dragOffsetY = dragWindowOffset.y;
                }
            }
            else if (f != null && f.isResizable()
                    && ((frameState & Frame.MAXIMIZED_BOTH) == 0)
                    || (d != null && d.isResizable())) {
                dragOffsetX = dragWindowOffset.x;
                dragOffsetY = dragWindowOffset.y;
            }
        }

        public void mouseReleased(MouseEvent ev) {
            isMovingWindow = false;
        }

        public void mouseDragged(MouseEvent ev) {
            if (isMovingWindow) {
                Point windowPt = MouseInfo.getPointerInfo().getLocation();
                windowPt.x = windowPt.x - dragOffsetX;
                windowPt.y = windowPt.y - dragOffsetY;
                w.setLocation(windowPt);
            }
        }

        public void mouseClicked(MouseEvent e) {}
        public void mouseEntered(MouseEvent e) {}
        public void mouseExited(MouseEvent e) {}
        public void mouseMoved(MouseEvent e) {}
	}

    public static void main(String[] args){
    	SwingUtilities.invokeLater(new Runnable(){
    		public void run(){
    			new FancyWindow(new Frame()).setVisible(true);
    		}
    	});
    }
}

If you have question regarding to this article or have a better code implementation, don’t hesitate to post your comments.

8 comments October 31, 2008


Recent Posts

Pages

Categories

Archives

 

December 2009
M T W T F S S
« Sep    
 123456
78910111213
14151617181920
21222324252627
28293031  

Flickr Photos

I get INSPIRED with a little help from my friends

Broken bricks – From the brick field

Marte ?

More Photos