Swing: Reliable way to be informed about mouse hover position - java

I am looking for a reliable way to be informed when the mouse moves and when the component beneath the mouse moves. While the first part can be rather easily implemented by using a MouseMotionListener, I am currently struggling with the second part.
Right now I have these two ideas:
1. Listen for all relevant changes
This one seems to be rather tough, so far I have
ComponentListener: When the component is moved
AncestorListener: When the ancestor is moved
MouseMotionListener: When the mouse is moved
And when a JScrollPane is used:
ChangeListener: When the view changes
Pros
Only triggers event based.
Cons
Breaks when JScrollPanes are used and you are not aware of it.
Additionally for my specific usecase I want to implement this hover behavior for a JEditorPane and the text layout could change. As described in the comments, for example changing text orientation of a text/rtf editor pane by pressing Ctrl + Shift + O.
2. Regularly check position and inform components
Regularly get the mouse position and inform the child component containing this position about it.
Pros
Catches all situations.
Cons
Always triggers, even if no change happened.
Is not immediate.
The component lookup is maybe rather expensive, especially with many nested components; I am currently using Container#findComponentAt but have not done any tests. (But maybe only as expensive as the lookup for MouseMotionListeners.)
Do you have other solution ideas, additions or changes to the ideas above?

Related

Does DragGestureRecognizer consume mouse events, and can I prevent that?

In a fairly complicated codebase, there is functionality both to
(a) drag objects places, implemented with DragGestureRecognizer,
(b) and the ability to drag boxes around things to select them, implemented via e.g. mousePressed() listeners.
Normally they behave "correctly".
However there are some objects which are marked immovable, and when the user begins a mouse gesture on top of one of them, the DragGestureRecognizer is finding it, and apparently consuming the mouse event.
What I'd like to be able to do is e.g. add something to my DragGestureRecognizer to say "oh look, we found an immovable object, let's not have this be a drag after all", and allow the dragging-a-box-around-things to take control.
I realize I'm not providing code because there is way too much to provide, but short of disabling the DragGestureRecognizer entirely (bad), I haven't found a way to get it to (selectively) turn loose of mouse events. Any help much appreciated!

Reduce sensitivity of mouse click detection

I've had this problem repeatedly over the years with AWT and Swing based interfaces: some mouse clicks events do not trigger mouseClicked in a MouseListener because the mouse moved at least one pixel during the click (which is most clicks with some mice). This is interpreted as a drag operation instead.
Is there a way to tell AWT/Swing to be a bit more permissive in its definition of a click?
Manually implementing a workaround is quite cumbersome if you want a full solution (if your components must also handle drag operations for instance):
Adding a unique MouseListener and MouseMotionListener to every component
Doing some sort of calculation of a click in mouseMoved, mouseDragged and mouseReleased (which requires measuring time elapsed, distance traveled...)
Forwarding the "fixed" mouse events to a new mouse input interface implemented by the components
There's got to be a better way! I'm hoping for a global setting but I just can't find one...
Related posts
https://stackoverflow.com/questions/20493509/drag-threshold-for-some-components-too-low
Making a component less sensitive to Dragging in Swing
Try setting the sensitivity of the D&D using:
System.setProperty("awt.dnd.drag.threshold", "5");
Note: this is only honored by List, Table, Text and Tree components!
See usages of javax.swing.plaf.basic.DragRecognitionSupport#mouseDragged() method.

Any methods in place to detect when focus is lost on a jfreechart plot/chart

this is hopefully going to be a simple one on a friday afternoon. I have a plot/jfreechart and i add a marker and change it based on the x,y location. The question i have is, is there anyway to tell when the jfreechart in quesition looses foscus. i.e the mouse has been moved from the jfreechart/plot on to another Jcomponent?
Cheers
The only way I imagine to do such a thing would be to add a listener to the chart, Either a MouseListener or FocusListener as these record 'live' events such as mouse movements or focus changes. I don't know how compatible these options are with your chart but these are likely to be your best (and possibly) only options. I would look into whether you are able top incorporate these into your program onto your chart and go from there.
Good Luck!

Should i redraw the GUI after change?

I have built a GUI displaying a matrix. It looks much like in excel where you have labels on the first row and first column. The cells contains either 1 or 0.
There's a JComboBox below the matrix. I can select an item from the JComboBox and click a button "add". This adds an extra row to the matrix with the JComboBox item as its name. My question is how i should handle expanding this.
Is it a good idea to have a method that redraws the whole window? Or should i try and just redraw the part that's been changed?
I thought of having a method like updateWindow() that could be used both for initiating the window and updating it if i make changes.
Is it a good idea to have a method that redraws the whole window? Or should i try and just redraw the part that's been changed?
It depends on what's in your window.
If you're drawing on a JPanel, by overriding the paintComponent method, redraw the entire JPanel. It's not worth the effort to try and redraw a part of a JPanel.
If you have a window made up of many JPanels, you can redraw just the JPanel with the changes.
I thought of having a method like updateWindow() that could be used both for initiating the window and updating it if i make changes.
It's generally a good idea to create methods to perform specific GUI tasks. I'd have separate initializeWindow and updateWindow methods for my own sanity. I usually separate the initialization of my GUI from the update of my GUI.
Read this excellent article, Sudoku Solver Swing GUI, to get an idea of how to put together a Swing GUI.
When you add components to a container, you will be invalidating that container's layout. This will automatically trigger a repaint, so the question becomes moot.
The real question becomes why?
Instead of messing about with labels and fields, you should just simply use a JTable. Check out How to use Tables.
This is optimized for performance, so if you're really concerned, this should provide a better solution, so long as you are firing the correct events to the required changes.
Unless you're finding yourself performance bound, I see no real reason not to redraw the entire window; sure there will be a performance hit but it should be negligible and your source will be simpler and easier to maintain. However, if you're finding yourself pressed for performance, I would suggest looking into implementing a "dirty rectangles" method of redrawing (i.e. your second approach).

Blackberry - How to implement ListField Smooth Scrolling?

Overview
I'm using a listfield class to display a set of information vertically. Each row of that listfield takes up 2/5th's of the screen height.
As such, when scrolling to the next item (especially when displaying an item partially obscured by the constraints of the screen height), the whole scroll/focus action is very jumpy.
I would like to fix this jumpiness by implementing smooth scrolling between scroll/focus actions. Is this possible with the ListField class?
Example
Below is a screenshot displaying the issue at hand.
(source: perkmobile.com)
Once the user scrolls down to ListFieldTHREE row, this row is "scrolled" into view in a very jumpy manner, no smooth scrolling. I know making the row height smaller will mitigate this issue, but I don't wan to go that way.
Main Question
How do I do smooth scrolling in a ListField?
There isn't an official API way of doing this, as far as I know, but it can probably be fudged through a clever use of NullField(Field.FOCUSABLE), which is how many custom BlackBerry UIs implement forced focus behavior.
One approach would be to derive each "list item" from a class that interlaces focusable NullFields with the visible contents of the list item itself -- this would essentially force the scrolling system to "jump" at smaller intervals rather than the large intervals dictated by the natural divisions between the list items, and would have the side benefit of not modifying the visible positioning of the contents of the list item.
Assuming you want the behavior that the user scrolls down 1 'click' of the trackball, and the next item is then highlighted but instead of an immediate scroll jump you get a smooth scroll to make the new item visible (like in Google's Gmail app for BlackBerry), you'll have to roll your own component.
The basic idea is to subclass VerticalFieldManager, then on a scroll (key off the moveFocus method) you have a separate Thread update a vertical position variable, and invalidate the manager multiple times.
The thread is necessary because if you think about it you're driving an animation off of a user event - the smooth scroll is really an animation on the BlackBerry, as it lasts longer than the event that triggered it.
I've been a bit vague on details, and this isn't a really easy thing to do, so hopefully this helps a bit.
unless you want to override the how the listfield paints or create your own wrapper, you will always have this issue, this is because each line is always visible when scrolling. Try using labelfield instead.

Categories

Resources