How to stop a transparent-fill circle getting mouse events inside it? - javafx

I want a Circle to respond to mouse events only when the mouse is on it's 'stroke' , i mean boundary. Of course, the circle has a transparent fill and a colorful stroke. Extending JavaFX Path looks painful to me, is there any way to do that with this Circle class?

Your solution does not work anymore in Java 9 but in your case you could just set the fill of the circle to null. This should have the same effect.

This solution doesn't work with Java 9:
Ok, finally I found an excellent way to do that. It may help others in the future:
javafx.scene.shape.Shape class has a Deprecated method
boolean impl_computeContains(double localX, double localY)
which invokes another method computeShapeContains(localX, localY, impl_configShape())
Now, scene graph decides whether a point is in a shape or not by
boolean contains(double localX, double localY) method from JavaFX.scene.Node which invokes that impl_computeContains method. So I had a look at those method and overrode the impl_computeContains mthod like this:
#Override
protected boolean impl_computeContains(double localX, double localY) {
float miterlimit =
(float) Utils.clampMin(getStrokeMiterLimit(), 1.0f);
return Toolkit.getToolkit().strokeContains(impl_configShape(), localX, localY, getStrokeType(),
Utils.clampMin(getStrokeWidth(), 0.0f), getStrokeLineCap(), getStrokeLineJoin(), miterlimit);
}
and boom!! it works!! All I did was, I removed the part which implemented what to do if the point was on the shape's interior part.

Related

JavaFX - How to use ImageView methods on Object type?

I'm trying to create an EventHandler for the mouse dragged event. I'll use this same handler to do the same thing with several ImageViews. Now this is what I did.
static EventHandler<MouseEvent> dragHandler = new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent e) {
e.getSource().toFront();
e.getSource().setTranslateX(e.getSceneX() );
e.getSource().setTranslateY(e.getSceneY() );
}
};
But apparently I can't use toFront or setTranslate methods or anything that I used for ImageViews because e.getSource returns an Object and these are ImageView methods that are not available to Object type. And apparently I can't simply cast that into an ImageView either by doing
(ImageView)( e.getSource() ).toFront();
I could simply use inner classes and lambda expressions but I thought there must be a more efficient way than just copy pasting the same lines like 15 times for each ImageView. So please enlighten me if there is.
Thanks in advance.
Casting would work, but the precedence of casting is below that of dereferencing (.), so your code example tries to downcast the result of (e.getSource()).toFront(), which doesn't work (as that has no type, since toFront() is void).
So
((ImageView) e.getSource() ).toFront();
would work.
However, it's usually better to register a different handler for each image view. There's no need to repeat code: just use any standard programming technique to avoid doing so. E.g. you can write a method:
private void registerEventHandler(ImageView imageView) {
imageView.setOnMouseDragged(e -> {
imageView.toFront();
imageView.setTranslateX(e.getSceneX() );
imageView.setTranslateY(e.getSceneY() );
});
// register other event handlers, as needed.
}
and then call the method for each image view (in a loop, if you have them in some suitable data structure).
Alternatively, you could create a method that creates the image views and registers any necessary handlers.
As well as being arguably cleaner code, these techniques also avoid the downcast, which in general is a good thing.

DayDream, detect pointer without using Event System

Google's new DayDream samples are using the Event System to detect if the pointer is on an object.
Previously it wasn't working like that at all, it was a reticle, and you would then create a Raycast between the Camera and the reticle, such as:
Vector3 rayDirection = GvrController.Orientation * Vector3.forward;
if (Physics.Raycast(origin, rayDirection, out hitInfo, Mathf.Infinity)) {
And then you detect if a specific Object is between the reticle and the Camera.
This way doesn't exactly work anymore. Google is now using the event system, and then checking if the reticle is positioned on an object.
Is there a way for me to check that for any object without using the Event System.
The Event System is a good method, it's just I have about 40 different objects that all work the same way, and implementing an event point/click for these 40 different objects seems like an overkill when previously I could just check an object by tag.
Anyone was able by any chance to be able to detect if the pointer is positioned on an object without using the Event system?
Raycasts don't seem to properly work anymore as the pointer seems to be more of a 2D object, just like a Mouse.
This works approximately, but not very well:
Vector3 origin = Head.transform.position + GvrController.ArmModel.wristPosition;
Vector3 rayDirection = GvrController.ArmModel.pointerRotation * Vector3.forward;
Any help would be appreciated :)
If you don't want to use EventTrigger component, you can simply use your same old script and implement IPointerEnterHandler, IPointerExitHandler, OnPointerClickHandler etc and use same compare tag method for every object.
I think its much more easy to use than custom raycast. As there is always a Graphics Raycaster (or Physics Raycaster for 3D Objects) at work so why not use what it has to offer.
public class MyOldScriptWhichUsedRaycasting: MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
public void OnPointerEnter (PointerEventData eventData)
{
if(gameObject.CompareTag("Grabable"))
{
//do stuff here.
}
}
public void OnPointerExit (PointerEventData eventData)
{
if(gameObject.CompareTag("Grabable"))
{
//do stuff here.
}
}
public void OnPointerClick (PointerEventData eventData)
{
if(gameObject.CompareTag("Grabable"))
{
//do stuff here.
}
}
}
Hope this helps

Prevent adding white space in VATNum

In TaxVatNumTable form, i need to eliminate white spaces in the field VATNum when a new record is inserted. Now, what i already did is to override the modifiedField method on the TaxVatNumTable:
public void modifiedField(FieldId _fieldId)
{
super(_fieldId);
switch (_fieldId)
{
case fieldNum(TaxVATNumTable, VATNum):
this.VATNum = strRem(this.VATNum," ");
break;
}
}
Works pretty well but is there another way to accomplish this? I am thinking at something like OnPreviewKeyDown event in WPF, check the pressed key and if space, do nothing. Is this possible?
The way you have done it is the best way to do it.
The TextChange method implies test for each keystroke, never do that in AX.

How to use intersect() method of Node Class in JavaFX?

JavaFX Node class provides two intersect methods:
intersects(Bounds localBounds);
and
intersects(double localX, double localY, double localWidth, double localHeight);
When and how can I use these methods?
as it name tells it is used to determine if a node is intersected with other node or not..
Example : If you're going to develop Zen pong game in javafx ,if ball hits the wall behind paddle then game over.
Code :
private Circle ball;
private Rectangle wall;
if(ball.intersects(wall.getBoundsInLocal()) {
//game over
}

ComboBox Qt Creator - how to create an event?

I have a Qt Form that contains 2 combo box messages. The second combobox message depends on the first combo box message. I mean that the dates from the second combobox message depends on the element that I select in the first combobox.
In this moment I have different dates in the first combobox. But the second combobox is not working. I need to creare a connect method or what?
Thx! APpreciate!
Could someone give me a short example?
It's fairly simple. A combobox emits the currentIndexChanged signal that also tells you the new index. Write a method that accepts an integer and changes the second combobox according to the integer (which is the index of the selection in combobox 1).
Here are some code sniplets from a working example.
Method declaration in your window/whatever class header:
public slots:
void setI1(int index);
Filling combobox 1, connecting the signal, e.g. in the constructor:
i1Box->addItem("Neutral", 0);
i1Box->addItem("2,856 K (Illuminant A, light bulb)", 2856);
// ...
connect(i1Box, SIGNAL(currentIndexChanged(int)),
this, SLOT(setI1(int)));
Implementation of the method:
void ViewerWindow::setI1(int index) {
// either use index directly, or, as in this case we have items holding an int:
int i1 = i1Box->itemData(index).value<int>();
// use the value to change second combobox here
}
If it does not work as expected, it is always helpful to print some debug output inside the method that should be called to see where it goes wrong in the chain.
Reference: http://doc.qt.nokia.com/latest/signalsandslots.html

Resources