This week's book giveaway is in the OO, Patterns, UML and Refactoring forum. We're giving away four copies of Refactoring for Software Design Smells: Managing Technical Debt and have Girish Suryanarayana, Ganesh Samarthyam & Tushar Sharma on-line! See this thread for details.
I'm trying to place a "draggable" Component inside a Panel. What I mean by that is I want to be able to have something like a JLabel for example that can moved around the Panel from one position to another (something like in Microsoft Powerpoint for instance, where you can drag objects from one place to another).
However I have no idea how I am going to tackle this problem because of 2 reasons:
1st reason: I have no idea which Layout for the Panel would be best for this task and I'm not even sure if a Panel is the best thing to use.
2nd reason: I briefly went through Java Sun's DnD (Drag and Drop) tutorial and don't quite understand this page (Default DnD Support). It says the DnD supports all swing components, but it gives a list of which components except drag/drop. Does that mean that I can't use a JLabel? Or simply that a JLabel is not recommended? Or neither?
Olivier Legat wrote:I'm trying to place a "draggable" Component inside a Panel. What I mean by that is I want to be able to have something like a JLabel for example that can moved around the Panel from one position to another
With JPanel(null) and using label.setLocation(..), we can drag any JLabel having a MouseMotionListener and a MouseListener.
As an example, here is a simple "Draggable" class which can wrap any JComponent that we want to make draggable. It contains a main method to show how to use it:
I suggest writing a new LayoutManager class that has an empty layoutComponent body but does have an implementation for preferredSize, that returns a Dimension such that all objects fit within that panel. It basically returns a Dimension(width, height), where width is the maximum of c.getX() + c.getPreferredSize().width and height is the maximum of c.getY() + c.getPreferredSize().height, for all child components c.
This way your panel will work better in JScrollPanes.
Olivier Legat wrote:Excellent! Thank-you so much this is exactly what I needed. I just don't quite understand the purpose of this Runnable interface though. Why must you catch an exception and what is this UIManager? :?
Nearly all updates to the user interface should be done on the Event Dispatcher Thread, and that includes creating your user interface. That's what SwingUtilities.invokeLater and SwingUtilities.invokeAndWait can do for you.
UIManager is a utility class that can help you with the overall look and feel of your components. This example tries to set the system look and feel, so the application will look like a Windows application when run in a Windows environment, and a GTK (mostly) if run in a Linux environment. However, this method can throw some checked exceptions, so you must catch these. Although the catch-all and ignoring is a bad idea, in this example it doesn't really matter because the only difference will be the way your application looks.
Oh wait, I've run into another problem I didn't foresee. How can I decide which components are on top and which ones are on the bottom. Logically I can see that which ever component is added in the end is placed on top. Does that mean that I need to remove components from the Panel and then add them back in the order I want to rearrange them? Or is there an easily alternative?
Using Container.remove(Component) and Container.add(Component, int) I can decide which position to place it in. Such as like this:
Joined: Nov 23, 2008
Olivier Legat wrote:How can I decide which components are on top?
We can implement a special container for the Draggables and dispatch mouse events from the Draggables to the container.
In "mouseReleased", the container can go through it's components:
Component comps = getComponents();
and assign zorder 0 (=top) to the last component intersecting the mouse position.
That way we are able to cycle through overlapping labels with mouse clicks.
To simple make the pressed Draggable come to top, we can add this in mousePressed of Draggable: