Skip to main content

JXLayer composite component

8 replies [Last post]
michelemarcon
Offline
Joined: 2008-10-23
Points: 0

I want to build a composite component based on JXLayer.

This composite component would allow its subclasses to draw behind and above the component itself.

The only annoiance is that JXLayer is final and can't be subclassed!

Here is my code. Please give me some advice on how can I implement my functionality.

abstract public class XComponent extends JXLayer{
public XComponent(){
setUI(layerUI);
}
public void drawBehind(Graphics2D g){}
public void drawInfront(Graphics2D g){}

AbstractLayerUI layerUI = new AbstractLayerUI() {
@Override
protected void paintLayer(Graphics2D g2, JXLayer l) {
drawBehind(g2);
super.paintLayer(g2, l);
drawInfront(g2);
}
};

}

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
alexfromsun
Offline
Joined: 2005-09-05
Points: 0

Hello Michelemarcon

> The only annoiance is that JXLayer is final and can't be subclassed!

Exactly!
All custom painting for JXLayer must be done it its LayerUI,
it can certainly be subclassed and reused after that

So you should override AbstractLayerUI rather than JXLayer
and implement drawBehind() and drawInfront() there

Thanks
alexp

michelemarcon
Offline
Joined: 2008-10-23
Points: 0

Sorry, I made some confusion.

In theory, my component should subclass JComponent instead of JXLayer, but still expose the same functionality (drawBehind/drawInfront)

pietblok
Offline
Joined: 2003-07-17
Points: 0

Not really sure what you mean, but here some code that may help you.

[code]
import java.awt.Graphics2D;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.AbstractLayerUI;

public class BehindAndFront {

public class XComponent extends JComponent {

private static final long serialVersionUID = 1L;

public void drawBehind(Graphics2D g2) {
g2.drawString("Behind", this.getWidth() / 3, this.getHeight() / 4);
}

public void drawInfront(Graphics2D g2) {
g2.drawString("Front", this.getWidth() / 2, this.getHeight() / 2);
}
}

public class XLayerUI extends AbstractLayerUI {

@Override
protected void paintLayer(Graphics2D g2, JXLayer layer) {
XComponent component = layer.getView();
component.drawBehind(g2);
component.drawInfront(g2);
}

}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
new BehindAndFront().createGUI();
}
});
}

private JComponent createContent() {
JXLayer layer = new JXLayer(new XComponent(),
new XLayerUI());
return layer;
}

private void createGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(createContent());
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

}
[/code]

Hope this helps

Piet

michelemarcon
Offline
Joined: 2008-10-23
Points: 0

Thanks for your help!
But unfortunately createContent() is not Matisse-friendly and I would like to create a XComponent that can be added to the GUI palette.

(This is why I originally put "XComponent extends JXLayer" on my code).

How can I wrap JXLayer's functionality inside a JComponent?

pietblok
Offline
Joined: 2003-07-17
Points: 0

Ah,

I know nothing of Matisse and GUI palettes, but anyway.

You could create a JComponent, that has a JXLayer instance as its only child. That component could have methods that act upon the JXLayer, its view and its layerUI. Could that component be easily added to the palette?

Piet

michelemarcon
Offline
Joined: 2008-10-23
Points: 0

Do you suggest that I do something like this?

abstract public class XComponent extends JComponent{
JXLayer layer;
public XComponent(){
layer = new JXLayer(this);
layer.setUI(layerUI);
}

public void paint(Graphics g){
layer.paint(g);
}

pietblok
Offline
Joined: 2003-07-17
Points: 0

No, more something like this:

[code]
import java.awt.BorderLayout;
import java.awt.Graphics2D;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.AbstractLayerUI;
import org.jdesktop.jxlayer.plaf.LayerUI;

public class BehindAndFront2 {

public static class MatisseComponent extends
JComponent {

private final JXLayer layer;

private static final long serialVersionUID = 1L;

public MatisseComponent() {
layer = new JXLayer();
}

public MatisseComponent(T view, LayerUI layerUI) {
this();
this.setView(view);
this.setLayerUI(layerUI);
super.setLayout(new BorderLayout());
super.add(layer, BorderLayout.CENTER);
}

public LayerUI getLayerUI() {
return layer.getUI();
}

public T getView() {
return layer.getView();
}

public void setLayerUI(LayerUI layerUI) {
layer.setUI(layerUI);
}

public void setView(T view) {
layer.setView(view);
}

public void specialMethod() {
// Do something special
}

}

public static class XComponent extends JComponent {

private static final long serialVersionUID = 1L;

public void drawBehind(Graphics2D g2) {
g2.drawString("Behind", this.getWidth() / 3, this.getHeight() / 4);
}

public void drawInfront(Graphics2D g2) {
g2.drawString("Front", this.getWidth() / 2, this.getHeight() / 2);
}
}

public static class XLayerUI extends AbstractLayerUI {

@Override
protected void paintLayer(Graphics2D g2, JXLayer layer) {
super.paintLayer(g2, layer);
XComponent component = layer.getView();
if (component != null) {
component.drawBehind(g2);
component.drawInfront(g2);
}
}

}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {

@Override
public void run() {
new BehindAndFront2().createGUI();
}
});
}

public void createGUI() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new MatisseComponent(new XComponent(),
new XLayerUI()));
frame.setSize(300, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

}
[/code]

I have some doubts about the paintBehind and paintInfront methods. Are you sure these methods should be implemented in XComponent? I would expect these methods to be part of your LayerUI implementation.

Piet

michelemarcon
Offline
Joined: 2008-10-23
Points: 0

> I have some doubts about the paintBehind and
> paintInfront methods. Are you sure these methods
> should be implemented in XComponent? I would expect
> these methods to be part of your LayerUI
> implementation.

No, I want to build components that extends XComponent, so that they will inherit the drawBehind and drawInfront capability (and reimplement them).

Thank you very much!

I'm now making experiments with your code, and everything looks good!