Skip to main content

LayerUI intercepts events by default?

8 replies [Last post]
ljnelson
Offline
Joined: 2003-08-04

Hello, Alex; I hope this is not a stupid question but I fear it may be.

What should the behavior be if I use only an unmodified AbstractLayerUI?

I have a panel with a button on it. I wrap it in a JXLayer, and I set a new instance of AbstractLayerUI on it.

When I do this, the button is no longer reachable by tabbing or by mouse clicking.

By default, do LayerUIs intercept events?

What I would like is for tabs to be processed as usual (i.e. the button should get focus), and for mouse clicks to be processed as usual (i.e. when they're delivered to children), but when mouse clicks are on a "dead zone" (gray space) I'd like my layer to intercept them.

Is there a good recipe for this?

Thank you,
Laird

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

Hello Laird

I just committed the patch that makes AbstractBufferedLayerUI.isIncrementalUpdate()
return true by default, this will eliminate this sort of confusion

Thanks!
alexp

ljnelson
Offline
Joined: 2003-08-04

Hi, Alex; yes, that probably makes sense.

I had another question (not very important): since in general Swing components are double-buffered by default, and since therefore when I paint on a layer I am painting, ultimately, to a back buffer already, then what advantage is there to double-buffering the buffer as you do in AbstractBufferedLayerUI? Does it really reduce painting artifacts? Or is the [i]determining whether or not to paint[/i] the thing that reduces the painting artifacts?

I would suspect the latter.

I would be curious to hear what you think about all this.

Thanks,
Laird

alexfromsun
Offline
Joined: 2005-09-05

Hello Laird

AbstractBufferedLayerUI allows you to use LayerEffects
by overriding getLayerEffects(JXLayer) method,
this is the main advantage of buffered ui's

If you don't need LayerEffects you should subclass AbstractLayerUI

Here is the example how to make your component grayscaled:
(I use BufferedLayerUI here, it is basically an AbstractBufferedLayerUI + setters)

[code]
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.BufferedLayerUI;
import org.jdesktop.jxlayer.plaf.effect.BufferedImageOpEffect;

import javax.swing.*;
import java.awt.image.ColorConvertOp;
import java.awt.color.ColorSpace;

public class BufTest {

private static void createGui() {
final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

JXLayer l = new JXLayer(new JButton("JButton"));
BufferedLayerUI buf = new BufferedLayerUI();
l.setUI(buf);

ColorConvertOp gsOp = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
buf.setLayerEffects(new BufferedImageOpEffect(gsOp));
frame.add(l);

frame.setSize(200, 200);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}

public static void main(String[] args) throws Exception {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
BufTest.createGui();
}
});
}
}
[/code]

Thanks
alexp

ljnelson
Offline
Joined: 2003-08-04

OK, thanks, Alex. I am 2-for-2 in the stupid questions department!

ljnelson
Offline
Joined: 2003-08-04

> I have a panel with a button on it. I wrap it in a
> JXLayer, and I set a new instance of AbstractLayerUI
> on it.

A little correction: originally I was setting an Abstract[i]Buffered[/i]LayerUI on it.

> When I do this, the button is no longer reachable by
> tabbing or by mouse clicking.

I figured out that I can restore most of the sub-component behaviors by making sure to remember to call setDirty(true), which I had not done in my processMouseEvent() method override. This at least restored [i]some[/i] painting artifacts to the button. This makes sense, because otherwise the layer doesn't know whether to repaint or not.

(I wonder if your processXYZEvent method signatures might be modified to return a boolean--to indicate whether they're dirty or not--so you force the user to make a decision?)

There may still be a problem--and perhaps I should expect it--when using an AbstractBufferedLayerUI on top of something like a text field. Specifically, I note that the caret does not flash, and you have to remember to call setDirty(true) for key events, not just mouse events. This makes some sense, since there's a back buffer involved, but I'm still uneasy--I'm not sure exactly why the caret flashes without a back buffer, but doesn't flash with one. I would have thought that whatever text field mechanism that triggers the repaint of the text field would cause the JXLayer machinery to pick up on the repaint request, but perhaps not?

I went back to using an AbstractLayerUI instead of an AbstractBufferedLayerUI, and when I make sure to call setDirty(true) in all the correct places things work fine.

I wonder if a little more documentation might be in order for the buffered UI classes? A warning, perhaps, that they don't play very well with JXLayer view children?

Thanks again for this great toolkit.

Best,
Laird

alexfromsun
Offline
Joined: 2005-09-05

Hello Laird

To enable incremental updates for the AbstractBufferUI you should override

[code]
boolean isIncrementalUpdate(JXLayer l)
[/code]
and make it return true, no setDirty() calls are needed in this case,
please read class' javadoc for more informations

Thanks
alexp

ljnelson
Offline
Joined: 2003-08-04

Thank you, Alex. I had read this Javadoc before, of course, but before I had run into this problem. It of course solves my problem exactly.

Best,
Laird

alexfromsun
Offline
Joined: 2005-09-05

Hello Laird

You are welcome

alexp