Mouse Listeners in Gluon - javafx

I've been trying to use listeners on gluon CharmListView for a while. It didn't work in my project so i decided to try it on the FIFTY STATES app. I added the code below:
charmListView.onMouseClickedProperty().set((MouseEvent event) ->{
Logger.getGlobal().log(Level.INFO, "Pick: {0}", new Object[]{event.getPickResult()});
});
When I launch the application, NO click fires aMOUSE_CLICKED event. When I scroll down slightly such that the a list header cell is fully docked like this,
the CharmListView fires the event only on a click on the top header cell.
INFO: Pick: PickResult [node = VBox#49f31558[styleClass=text-box], point = Point3D [x = 133.0, y = 13.0, z = 0.0], distance = 1067.366530964699
No other click anywhere else on the list fires an event.
I've tried adding the same listener to the normal ListView and a MouseEvent is always fired after a click on any area of the ListView. So now I'm stuck because I cannot set a listener to get a selected item.

The CharmListView control is mainly intended for mobile applications, where you use scroll and swipe gestures. But these gestures trigger mouse clicked or pressed events.
If the list cells contain some event handler to process the latter, the only way scroll works is by consuming them, otherwise whenever you scroll the list, the cell event handler will be processed as well, when you start scrolling.
That's the reason why setOnMouseClicked() doesn't trigger any event if you click on the listView.
For accessing the list view selection model, please refer to this question.

Related

how can i implement drag and drop in urho 3d view?

I have added 3d view objects using urhosharp for my xamarin uwp/ios/android project . The only event that work is touch event, but i also want to use drag and drop so that the objects can move to different locations within the 3D view. Any suggestions?
https://us.v-cdn.net/5019960/uploads/editor/ni/u16pg79v2m62.png
Haven't used urhosharp yet , but here are some suggestions about using of drag and drop, not sure if it helps here for you.
urhosharp: Basic Actions
From document of urhosharp , there is some bascic actions explains,but no drag and drop in it.Maybe you can do it by combining actions and drag methods on each platform. But this requires you to try.
UWP: reference link here
Here's an overview of what you need to do to enable drag and drop in your app:
Enable dragging on an element by setting its CanDrag property to
true.
Build the data package. The system handles images and text
automatically, but for other content, you'll need to handle the
DragStarted and DragCompleted events and use them to construct your
own data package.
Enable dropping by setting the AllowDrop property to true on all the
elements that can receive dropped content.
Handle the DragOver event to let the system know what type of drag
operations the element can receive.
Process the Drop event to receive the dropped content.
Code example:
<Grid AllowDrop="True" DragOver="Grid_DragOver" Drop="Grid_Drop"
Background="LightBlue" Margin="10,10,10,353">
<TextBlock>Drop anywhere in the blue area</TextBlock>
</Grid>
private void Grid_DragOver(object sender, DragEventArgs e)
{
e.AcceptedOperation = DataPackageOperation.Copy;
}
IOS: reference link here
With drag and drop in iOS, users can drag items from one onscreen location to another using continuous gestures. A drag-and-drop activity can take place in a single app, or it can start in one app and end in another.
Use drag items to convey data representation promises between a source app and a destination app.
Adopt drag interaction APIs to provide items for dragging.
Adopt drop interaction APIs to selectively consume dragged content.
Demonstrates how to enable drag and drop for a UIImageView instance.
Code of example:
func customEnableDragging(on view: UIView, dragInteractionDelegate: UIDragInteractionDelegate) {
let dragInteraction = UIDragInteraction(delegate: dragInteractionDelegate)
view.addInteraction(dragInteraction)
}
func dragInteraction(_ interaction: UIDragInteraction, itemsForBeginning session: UIDragSession) -> [UIDragItem] {
// Cast to NSString is required for NSItemProviderWriting support.
let stringItemProvider = NSItemProvider(object: "Hello World" as NSString)
return [
UIDragItem(itemProvider: stringItemProvider)
]
}
Here is a sample for Xamarin IOS.
Or you can using UIPanGestureRecognizer in IOS to move view.Here is Walkthrough: Using Touch in Xamarin.iOS.All you need to do is let view.center follow panGesture to change.
Android: reference link here
With the Android drag/drop framework, you can allow your users to move data from one View to another using a graphical drag and drop gesture. The framework includes a drag event class, drag listeners, and helper methods and classes.
There are basically four steps or states in the drag and drop process:
Started:In response to the user's gesture to begin a drag, your application calls startDrag() to tell the system to start a drag.
Continuing:The user continues the drag.
Dropped:The user releases the drag shadow within the bounding box of a View that can accept the data.
Ended:After the user releases the drag shadow, and after the system sends out (if necessary) a drag event with action type ACTION_DROP, the system sends out a drag event with action type ACTION_DRAG_ENDED to indicate that the drag operation is over.
Table. DragEvent action types:
Or in Android can use onTouchEvent to move view, need to calculate position of the view.Walkthrough - Using Touch in Android
The main thing is to handle pressing and moving two messages, overloading onTouchEvent. Mathematical knowledge (translation): Record the coordinate point when ACTION_DOWN, and calculate the translation amount according to the current position and the position when pressed at ACTION_MOVE. Refresh the control, causing the control to redraw, and move the coordinates of the upper left corner of the drawing when redrawing.
Here also has a discussion about Drag & Drop in Xamarin forms.It may be helpful.

JavaFX ComboBox: Receive mouseclick/keypress events from ListView

I start with the question and then describe the problem more in detail:
Question:
Is there a way to receive events from the listview of a JavaFx ComboBox directly (ComboBox consists of a listview and a textfield as far as I understand)? I would like to find out which element of the list has been clicked by mouse or which element was selected when the user pressed enter on the keyboard (after navigating with Up/Down Arrows in the list). I therefore need to receive the mouse click event or the keypress event on the listview, but all I can get so far are events on the combobox itself which turned out to be only changes in the textfield of the combobox.
Detailed problem description:
I have a JavaFx Application with a combobox where the idea is that the value is directly added to another list when the user clicks on an entry in the combobox list (when the popup of the combobox is open). Additionally, when the user navigates in the combobox list with the arrow keys on the keyboard and he presses enter, the currently selected value should be taken and added to the other list. However so far I have not found out how I can implement this feature with the standard JavaFx combobox.
Tried:
The first solution I tried was to add a change listener on the combobox's valueProperty (this is the value that is displayed in the textfield when the popup is closed). So when the user clicks on a listentry, the popup closes and the clicked entry is put into the value field, changes the value and therefore fires my change listener. This worked well with the mouse, but keyboard navigation did not work correctly because everytime the user navigates down or up on the list, the value field of the combobox is updated with the currently selected listentry and therefore fires my changelistener every time (which in turn adds the value to my other list, while it should only be added on enter keypress).
The next solution was to not add a listener to the valueProperty, but to the showingProperty. Everytime the combobox popup closes, the current value of the value field is taken and added to the other list. This works again well with the mouse, but still has issues with keyboard navigation. While it now correctly handles up/down navigation in the list and enter keypresses, the problem is now when you try to cancel the selection. When you press escape, the value is taken as well and added to the other list like you would have pressed enter. The problem with this approach is that I cannot find out with which keypress the popup has been closed.
So the next idea I had is to add an event filter to the combobox itself with the addEventFilter Method of the ComboBox with code similar to the following (also proposed here StackOverflow):
ComboBox comboBox = new ComboBox();
comboBox.addEventFilter(KeyEvent.KEY_PRESSED, (event) -> {
// do stuff
});
But the event filter never gets called when the combobox popup is open. It is only called when the popup is closed, which leads me to the assumption that the event is consumed by the listview. So the only solution to the problem seems to be to somehow capture the events from the listview itself. And that leads back to the question at the beginning of this post. Sorry for the long explanation.:-)
Came across this question while looking for something else. It touches on something I've worked on before so assuming I understand what you're trying to accomplish and also that this is still relevant here are a couple of ideas.
To keep the other list (list #2) in sync with the combo box for mouse clicks try:
A ChangeListener on the selectedItem property for the combo box's selectionModel. Clicking an item in the popup (drop-down) list view will change the selectedItem value and close the Window that 'owns' the list view, or
An event handler to the combo box for the event type ComboBoxBase.ON_HIDDEN which gets fired when the list view closes (or better said 'becomes hidden').
The ChangeListener may be problematic inasmuch as the selection models for the combo box and the list view are linked at a low level, so that changes to the selectedItem value for the list view which will be triggered when navigating with key strokes will necessarily be handled by the ChangeListener. Since you want to sync the combo box and list #2 only when the ENTER key is pressed, this will probably not work. But that still leaves the event handler idea to try.
As for ENTER key press, you need to get a handle for the list view itself, and then add whatever behavior (listeners/event handlers) as needed. You do this by getting the skin for the combo box, which should be an instance of ComboBoxListViewSkin, and then get the list view by invoking the getPopupContent() method for the skin; it returns the popup list view as a Node so you'll to recast the returned value but no big deal.
Hope this helps.
The idea of the below code is that ListView is created once the combobox is loaded in the JavaFX scene. Therefore, we add a listener on the combobox to check when it appears on the scene, and then through "lookup" method we get its listview and add a listener to it.
In the example, I have set a MouseEvent listener but you can easily adjust it for keys as well.
private EventHandler<MouseEvent> cboxMouseEventHandler;
private void initComboBox() {
ComboBox<String> comboBox = new ComboBox<String>();
comboBox.getItems().add("Item 1");
comboBox.getItems().add("Item 2");
comboBox.getItems().add("Item 3");
comboBox.sceneProperty().addListener((a,oldScene,newScene) -> {
if(newScene == null || cboxMouseEventHandler != null)
return;
ListView<?> listView = (ListView<?>) comboBox.lookup(".list-view");
if(listView != null) {
cboxMouseEventHandler = (e) -> {
Platform.runLater(()-> {
String selectedValue = (String) listView.getSelectionModel().getSelectedItem();
if(selectedValue.equals("Item 1"))
System.out.println("Item 1 clicked");
});
}; // cboxMouseEventHandler
listView.addEventFilter(MouseEvent.MOUSE_PRESSED, cboxMouseEventHandler);
} // if
});
} // initComboBox

Recognize a holding/long touch on a list component in Flex Mobile

I´am trying to create my own custom list component in a Flex mobile Project which fires an Event when the user touches a listitem and holds the finger down for a given time.
Some kind of "longTouch"-Event like its implemented on native android listitems to edit the entry for example.
I tried to listen for the MOUSE_DOWN Event to start a timer and dispatch an event when the timer finished. But this approach failed because i cant get the listitem that was pressed by the user because the List component updates the "selectedItem"-property only after the user lifts his finger from the list.
thanks in advance
Andre Uschmann
There is no longTouch (or longPress) event exposed through the Flash Player Native APIs.
One option is to roll your own using TOUCH_BEGIN, TOUCH_END, and a timer.
Basically:
When user starts the touch, start the timer.
When the touch_End event fires; check the timer to see how long it has been running using currentCount. If it is long enough to be considered a "long touch", then dispatch your custom longPress event. If not; then stop the timer and ignore.
This could all happen inside the renderer; so you'd know exactly what item was pressed.
I expect this would be more solid than using mouse events, which seem to be inconsistent on touch based devices

How does Flex click event work inside of containers?

I have a VBox, I assigned a handler to click, and inside the VBox I have components such as images and texts with no handler assigned for click. Would the click function be called when I click on the text and image? If not how can I make it so without assigning handlers individually, but on the container level?
Thanks
Click events "bubble" in Flex. When you click on an images, it bubbles up to its parent, then that parent's parent and so on until there are no more parents left.
If any of these have click listeners they will trigger when they are reached in the bubbling process.
Also in the event the currentTarget will refer to the object that has the listener, and the target will be what was actually clicked.
So in your case if they click the image, the event will bubble up to the container triggering the event, in your listener function the clicked image will be the event.target and the container will be the event.currentTarget.
Also in the bubbling process, it actually starts from the root parent down, this is called the capture phase, then bubbles back up. Your event will trigger when it bubbles back up unless you specify useCapturePhase = true in the event listener. This is how you can stop an event from going to its children. If you use the capture phase then call event.stopPropagation() inside the event listener then the container will receive the event but the child image will not.
It's taken an hour for an answer to this question... it probably would have been faster to just try it. :)
But yes, click events bubble up to parent containers. Adding the handler to the VBox should be fine.
I was pretty sure that containers, such as VBox do not dispatch click events; unless they are bubbled up from the children.
However, clicking on items in your container should trigger the listener on your container, as the Click event bubbles.

Event propogation whilst container is not initialised

I have a Canvas (lets call it the Drop Box) which users can drag and drop external files onto. Next to this I have a ViewStack, of which one of the layers is a Canvas with a TileList. I have successfully managed to code it so that the items dropped onto the Drop Box appear in the TileList. I simply capture the darg drop event (lets call this event A) and dispatch a new one that the TileList is listening for (lets call this event B).
However, this only works if the ViewStack selectedIndex is set to that of the Canvas with the TileList. If the Canvas with the TileList isn't selected then the event listener which is added to the TileList at CreationComplete level (event B), won't be called until after the drag drop event has dispatched (event B). This means that something is firing before something even has a chance to listen for it!
I've tried looping until the Canvas with the TileList is completely drawn, but this causes the app to hang.
I've also tried passing the event to the Canvas and storing it locally, but when I attempt to access the clipboad of the event I get an error (dead clipboard).
Effectively I want to only dispatch the event to the Canvas after it's had a chance to load, and add the event listener to the TileList.
Any ideas? :)
Maybe setting creationPolicy="all" for View Stack will help? All it's children will be created at startup.

Resources