Use event in multiple different components - java

I have a JscrollPane which holds a JPanel on which I draw. I would like to use the MouseWheelEvent to:
zoom the (with CTRL+Wheel) Panel content
and to scroll the scrollpane (with just the wheel)
Each action by itself works, but I dont't manage to make both work. As soon as I add a MouseWheelListener to the JPanel, the event does not arrive at the JScrollPanels listner.
How can I get the MouseWheelEvent to be forwarded the JScrollPanes MouseWheelListener if it has not been used in the JPanel?
EDIT: Thanks for the hint: Is there also a way to make both listeners listen? Because the scrolling in the scrollpane is actually default implemented. So is there a way to use it without any additional implementation?
Thanks & Regards,
Marc

Make your custom listener dispatch the events (which it doesn't want to handle itself) to the sender's parent, eventually, the scrollPane will pick them up:
final MouseWheelListener wheel = new MouseWheelListener() {
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (shouldHandleHere(e)) {
LOG.info("do-my-own-stuff");
} else {
LOG.info("dispatch-to-parent");
e.getComponent().getParent().dispatchEvent(e);
}
}
public boolean shouldHandleHere(MouseWheelEvent e) {
return (e.getModifiersEx() & MouseWheelEvent.CTRL_DOWN_MASK) != 0;
}
};

When you register a listener, you assign a method to execute when a particular behaviour is detected. Suppose I have :
Listener1 executing method1
Listener2 executing method2
If listener1 prevent the listener2 from listening, you just have to call method1 and method2 when listener1 is triggered.

Related

How to remove a mouse wheel listener in SWT

I am trying to remove and replace a mouse wheel listener on a ScrolledComposite in SWT. The scrolled composite has a removeMouseWheelListener method, however it has no way of gaining access to a the mouse wheel listener to remove it. I have tried the getListeners() method:
MouseWheelListener mouseWheelListener = (MouseWheelListener) scrollable.getListeners(SWT.MouseWheel)[0];
but this produces an a casting error so getListeners must not retrieve the same type of listeners. I have tried creating a new listener and removing it from the ScrolledComposite:
MouseWheelListener scroller = new MouseWheelListener() {
#Override
public void mouseScrolled(MouseEvent e) {
Point currentScroll = scrollable.getOrigin();
scrollable.setOrigin(currentScroll.x, currentScroll.y - (e.count * 5));
}
};
scrollable.removeMouseWheelListener(scroller);
This does not remove the listener though. Of course, if I had access to the original MouseWheelListener that was added this would not be a problem, but I don't.
Thank you.
getListeners will return a listener of type TypedListener for a mouse wheel listener.
TypedListener.getEventListener() will return the MouseWheelListener.

When I modify a JPanel after it becomes visible, paintComponent gets called before componentResized

I have a data plot with a color bar that's a JPanel with a layout that has two JPanels inside of it. One JPanel is the data plot itself, and the other is the color bar. I'd like to add functionality so the color bar can be toggled on and off, and I've gone about this by simply removing the JPanel containing the color bar. Something like this:
public class Data2DPlotWithColorBar extends JPanel {
public Data2DPlotWithColorBar() {
this.data2DPlot = new Data2DPlot();
this.colorBar = new VerticalColorBar();
this.setPlot();
}
public final void toggleColorBar() {
enableColorBar = !enableColorBar;
setPlot();
}
private void setPlot() {
this.removeAll();
this.setLayout(new BorderLayout());
if (enableColorBar) {
this.add(colorBar, BorderLayout.EAST);
}
this.add(this.data2DPlot, BorderLayout.CENTER);
this.revalidate();
this.repaint();
}
private final Data2DPlot data2DPlot;
private final VerticalColorBar colorBar;
private boolean enableColorBar;
}
The problem is that when the color bar is removed, the data plot has a component listener with the componentResized method overrided which correctly resizes the data (maintains fixed aspect ratio) to fit the size of the JPanel. Something like this:
public class Data2DPlot extends JPanel {
...
#Override
public final void componentResized(ComponentEvent e) {
double scaleFactorBuf = Math.min((double)getPixelMaxViewWidth()/getNativeWidth(),
(double)getPixelMaxViewHeight()/getNativeHeight());
// Make sure scaleFactorBuf isn't close to zero
if (Math.abs(scaleFactorBuf) > MathUtilities.LAMBDA) {
scaleFactor = scaleFactorBuf;
}
}
...
#Override
protected final void paintComponent(Graphics g) {
super.paintComponent(g);
....
}
}
It turns out that as-is, the dataplot is not resizing properly. I did some debugging and I found out that componentResized gets called AFTER the paintComponent method when I toggle the color bar off and on. This means the image gets painted, and then the scaleFactor gets updated afterwards, which is incorrect. The only way I've been able to fix it so far is to call repaint() at the very end of the componentResized method. However, repaint() is already called when the component is resized, so I feel like this is the incorrect approach. Some googled led me to solutions involving the use of revalidate and repaint after modifying a JPanel on demand. However, any combination of doing this still led to componentResized being called after repaint. Is there a standard fix for this?
An answer proposed in this thread offers an easy solution; rather than overriding the componentResized method, do the setBounds(int,int,int,int) one.
The call order of componentResized, setBounds, and repaint is strange; on program startup it is like this;
setBounds
componentResized
repaint
while if you manually resize it later (I did not test with in-code resizing order) it goes
setBounds
repaint
componentResized
By setting your flags in setBounds rather than componentResized, you can know to recompute your repaint size-sensitive variables on panel resizing, effective immediately.

Displaying a JPanel on JFrame by a label click

I have tried it over and over.Its not working.When I click the lablel, nothing happens.
private void jLabel1MouseClicked(java.awt.event.MouseEvent evt)
{
setLayout(new BorderLayout());
JPanel o = new JPanel ();
o.setPreferredSize(new Dimension(122,200));
o.setBackground(Color.red);
add(o,BroderLayout.CENTER);
// TODO add your handling code here:
}
Looks a stupid question, but, are you sure that your method is getting called? Is your object registered as an event listener of this label?
Just to be sure, you should implement the MouseListener interface:
public class YourClass () implements MouseListener{
public YourClass(){
...
label.addListener(this);
}
// and then implement the method to handle the event
public void mouseClicked(MouseEvent e) {
// TODO: Handle the event
}
}
jLabel1MouseClicked does not look like the event handler method
EDIT: By the way, you may want to implement the other methods in this interface, even if you don't need them. Check the documentation: MouseListener example
if the Listener is implemented correctly, then you should change this
o.setPreferredSize(new Dimension(122,200));
with this
o.setSize(122,200);
you can put a setVisible method too, but it should work without it, too
I Think you are using Netbeans, If yes then the method you showed is auto-generated which means that it has correctly implemented Listeners in it's Auto-Generated Code Segment, well for now this means that you have error in Showing JPanel not in implementing listener, so I found some suggestions for you,
you have written BroderLayout but its BorderLayout but this seems to be a typo when posting Question.
Secondly you are not updating your frame, just adding the JPanel is not enough for showing it, so Add this code, this.revalidate();
so finally your block code should be like this,
private void jLabel1MouseClicked(java.awt.event.MouseEvent evt)
{
setLayout(new BorderLayout());
JPanel o = new JPanel ();
o.setPreferredSize(new Dimension(122,200));
o.setBackground(Color.red);
add(o,BorderLayout.CENTER);
revalidate();
}

Is it possible to make hover effect on images using graphics?

I am trying to make hover effect on multiple images in Swing using graphics, I know this can be done by using CSS but confused to make this effect in Java, can anybody help me?
Yes, it is quite possible to do that.
Assume you have a JPanel with an image inside it that you want to change every time the user hovers over it. The code would be something like this:
JPanel panel = new JPanel(); // create a JPanel
this.setupGI(panel); // prepare your background
panel.addMouseListener(new MouseHandler()); // add a listener
this.getContentPane.add(panel); // add it to JApplet / JFrame
This is to add the listener where MouseHandler will be your custom handler class.
class MouseHandler extends java.awt.event.MouseAdapter{
#Override public void mouseEntered(MouseEvent e){
// your logic here
}
#Override public void mouseExited(MouseEvent e){
//
}
}
Now, how the MouseHandler class will get access to the JPanel, well that is up to you. Usually, I make the handler class a sub-class so it has access to all the methods, fields of the enclosing class. Alternatively, you can make getter and setter methods. It is up to you.
More here: http://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html
Use MouseListener with events mouseEntered and mouseExited.

What does a addActionListener do?

I have the following code:
JButton button = new JButton("Clear");
button.addActionListener(this);
As far as I understand, I create a button on which it is written "Clear". Then I have to associate an action with this button (what will happen if the button is pressed) and it is done by addActionListener. Is it right?
But what I do not understand is where the action is specified. The press of the button should clear text area and, as far as I understand, there should be somewhere a code which clear the text area. But in the given example there is only "this" in the arguments of the addActionListener().
How does the program know that it should clear the text area when the button is pressed?
If it is needed, the full code is given here.
An ActionListener is a callback mechanism. Whenever a control it is added to fires an ActionEvent, the public void actionPerformed(ActionEvent e) method will be invoked.
What I do not understand is where the actionPerformed is called. I see that it is defined within the class but there is no place where this method is called.
This is called by the internal mechanisms of the UI component. Conceptually, you can think of the code looking a bit like this:
public class Button {
private final List<ActionListener> listeners = new ArrayList<ActionListener>();
public void addActionListener(ActionListener l) {
listeners.add(l);
}
public void click() {
ActionEvent event = new ActionEvent(this, 0, "click");
for (ActionListener l : listeners) {
l.actionPerformed(event);
}
}
}
Each JButton, has an EventListenerList. Calling addActionListener(this) adds your ActionListener, a callback function named actionPerformed(), to the list. You can see an outline of the code that calls your method here. The actual fireActionPerformed() method is in AbstractButton. A JButton is a JComponent, which you can see listed among the various classes that use the event listener list mechanism.
You call button.addActionListener( this ), because this implements the interface ActionListener. When the button is clicked, the method actionPerformed(ActionEvent e) (defined by the interface and implemented by your class) is called.
Basically, the mechanism of UI event handling is the JVM queue's events, and each type of event has its subscribers. When an event is fired, like the button is clicked, the JVM will accordingly delegate the processing to the event's subscriber. And this subscriber class has to define the method, or, event handler, to process the event.
In your case, when calling
button.addActionListener(this);
the code actually subscribes this KeyEventDemo instance to the event of type click. Then, when the button is clicked, the KeyEventDemo's method of actionPerformed will be triggered.

Categories