JavaFX scene has an object of class inherited from the Region. This object has a handler of MOUSE_DRAGGED event. When this handler is called, all object's child nodes are removed and new child nodes are added. The problem is when all children are removed from my object, it doesn't receive any events anymore, because target of MOUSE_DRAGGED event is removed child node. How to solve it?
I cannot use setMouseTransparent method, because some elements inside my object have mouse event handlers.
Ok, perhaps I got the question:
A region has many children. If the user left-clicks and dragges on these children, they will be modified or even removed. As the Mouse-Drag event is 'locked' to the first child where the drag started, no other child will receive further events if the mouse is dragged over some of the other children.
You might benefit from the fact, that the MouseDrag event is passed to the parent region after removing the child. So it is possible to register an onMouseDragged handler on th eparent regon receiving that event. Now the handler is able to 'pick' any childs below mouse for further actions using event.getPickEvent():
void mouseDragPop(Pane region) {
region.setOnMouseDragged(e -> {
Node node = e.getPickResult().getIntersectedNode();
if (node instanceof Circle) {
region.getChildren().remove(node);
}
});
for (int i = 1; i < 10; i++) {
final int n = i;
Circle circle = new Circle(20);
circle.setTranslateX(0);
circle.setTranslateY(0);
circle.setFill(Color.rgb(180, 200, 170));
circle.setLayoutX(System.nanoTime()/1000 % 200);
circle.setLayoutY(System.nanoTime()/3000 % 100);
region.getChildren().add(circle);
circle.setOnMouseDragged(e -> {
region.getChildren().remove(circle);
e.consume();
});
}
}
Now you are able to click and 'pop' all circle on your mouse-drag way...
Related
I have an ASP.net webForms, using .NET 4.7.2 TreeView.
I'm using the TreeView component to render a webpage. this renders the tree as a series of tables for node labels and div elements containing child nodes.
I'm trying to add a click event to the node, which is an element located in the table.
The TreeNode has been overriden, to make use of RenderPreText, which adds an attribute role="treeitem" to each of these node's label.
ie
protected override void RenderPreText(HtmlTextWriter writer) {
writer.AddAttribute("role", "treeitem");
}
The following code is what I'm using to add the click event to each node's label element:
window.addEventListener("load", (event) => {
var treeItems = document.querySelectorAll('[role="treeitem"]');
for (var i = 0; i < treeItems.length; i++)
{
treeItems[i].addEventListener('click', OnNodeSelect);
}
});
function OnNodeSelect(event) { alert('Node Selected'); }
The issue i'm having, is that when the node is selected, the event fires and is then removed, so can only be clicked a single time.
What am I doing wrong, how do I add an event that doesn't get removed after single activation?
I want to use .lookup() so that I can create an event for when the content of a TextArea is clicked, but I get null when I use textArea.lookup(".content"). After searching why this is, I found out that it returns null if called before stage.show(). My next reaction was to somehow check for an event that is cast once the stage is shown, but that event is only accessible if you have access to the stage itself, which I do not in this case. What else can I do?
Don't register the handler at the content node. Let TextArea deal with the creation of the content node on its own, register a event handler at the TextArea directly and use the pickResult of the event to determine, if the click happened inside the node with style class content.
textArea.setOnMouseClicked(evt -> {
Node n = evt.getPickResult().getIntersectedNode();
while (n != textArea) {
if (n.getStyleClass().contains("content")) {
// do something with content node
System.out.println("content: " + n);
break;
}
n = n.getParent();
}
});
Generate a layout pass on the node:
node.applyCss();
node.layout();
as defined in the answer to:
Get the height of a node in JavaFX (generate a layout pass)
After that, your lookup functions on the node should work as expected.
When I select several QGraphicsItem (with Ctrl key) I can move them together, but the mouseMoveEvent is triggered only for the item that actually receives the event. Is there a way to make every selected items receive the event ? I can't find it in Qt's doc.
Could I group selected items together and handle it within QGraphicsView's mouseMoveEvent ?
Thanks a lot for any help :)
No there is no default way to do what you want as far as I know. Something you could do is the following:
Subclass QGraphicsScene and implement the mouseMoveEvent
In the mouse move event check if there is an item at the event position using the itemAt function
If there is an item and it is selected (isSelected), get all selected items of the scene.
For all selected items call the same function you would call.
Sample code follows:
void mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent)
{
QPointF mousePosition = mouseEvent->scenePos();
QGraphicsItem* pItem = itemAt(mousePosition.x(), mousePosition.y());
if (pItem == NULL)
{
QGraphicsScene::mouseMoveEvent(mouseEvent);
return;
}
if (pItem->isSelected() == false)
{
QGraphicsScene::mouseMoveEvent(mouseEvent);
return;
}
// Get all selected items
QList<QGraphicsItem *> items = selectedItems();
for (unsinged i=0; i<items.count(); i++)
// Do what you want to do when a mouse move over a selected item.
items[i]->doSomething();
QGraphicsScene::mouseMoveEvent(mouseEvent);
}
I'm reading between the lines of your question a little, but it sounds like you might be better served by implementing QGraphicsItem::itemChange on your QGraphicsItem class(es). This will get called whenever the position changes--whether by mouse, keyboard, programmatic, etc. You can even cancel the change if you want to.
http://doc.qt.io/qt-5/qgraphicsitem.html#itemChange
I have made a hierarchy in which there is a main page, using add element i have attached a component mxml of type group. There is a single button on main page when clicked it should add children of type group in that group type mxml component along with two buttons. Now using one of buttons i am attaching another component mxml type group. the problem is even they overlap i can still excess the children groups of first group component mxml. how can i stop this mouse events to happen.
I think those kind of events usually bubble up to parent components.
You can try using the following code in your mouse click event listener to stop further propagation:
private function onMouseClicked(event: MouseEvent): void {
event.stopPropagation();
... do whatever you wanted when smth was clicked ...
}
By setting enabled, mouseChildren, mouseEnabled to false, you will disable the entire component and it's children. example below
private var myPreviousGroupComponent:Group = null;
function addNewGroup():void
{
if(myPreviousGroupComponent != null)
{
myPreviousGroupComponent.enabled = false;
myPreviousGroupComponent.mouseChildren = false;
myPreviousGroupComponent.mouseEnabled = false;
}
var newGroup:Group = new Group();
addElement(newGroup);
myPreviousGroupComponent = newGroup;
}
Is there a way to enable dragging of only leaf nodes in a tree component?
First you need to intercept the dragStart event from your tree
dragStart="tree_dragStartHandler(event)"
Then in the event handler you can check to see if the selected item is a branch, if it is then you cancel the dragStart event's default behavior with preventDefault()
protected function tree_dragStartHandler(event:DragEvent):void
{
var item:Object = event.currentTarget.selectedItem
if (tree.dataDescriptor.isBranch(item)) {
event.preventDefault();
}
}