Dave Tolls wrote:With FX (as you say) you get the full touch support.
It's a mix. There are separate
touchPressed and
touchReleased events that JavaFX supports, but they don't act as alternatives to the mouse events. Instead, if you want to assign an "action" to a JavaFX Button, that action will fire when you click the button with the mouse, and it will also fire when you press the button through the touch screen. That's because the touch screen emulates a mouse, and generates the same
MOUSE_PRESSED,
MOUSE_RELEASED, and
MOUSE_CLICKED events the mouse generates. That means the touch screen will also fire the action. But, owing to the silly way the events are timed (meaning that you don't get the
MOUSE_PRESSED event until
after you lift your finger), you can't make the touch screen behave like a real electromechanical button would behave. In fact, it doesn't even take the focus or change in any other way until you lift your finger (unless you
move your finger while you touch the screen, and I cannot figure that behavior out at all).
Now, you can add
touchPressed handlers to fire the action for you, but then you will fire the action twice: once when the
touchPressed handler fires it, and once more when the touch screen sends the three mouse events after you lift your finger. You also have to take the focus and arm the button in the
touchPressed handler, if you want the same visual feedback the mouse gives you.
To prevent the second firing, you can set a "skip" Boolean flag in the
touchPressed handler, and have the action handler consult it. If it's true, set it false and just return. If it is false, execute the action.
But this gets worse...
If you press the button through the touch screen, take the focus, arm the button, fire the action, and set the skip flag, and
then drag your finger off the button before taking your finger off the screen, the
MOUSE_PRESSED event will occur, but the
MOUSE_RELEASED event will not occur (for that button, anyway). This means the action will
not fire a second time, because the necessary mouse events don't all happen. Thus, with the skip flag set, the next time you do press or click the button, the action will not be executed, because the skip flag is still set.
To get around this, I added a
touchReleased handler. This is always called, even if you drag your finger off the button before taking it off the screen. In that handler, I can check to see if the event happened inside the visible shape of the button (there's actually a library method for that). If so, then (and only then) do I set the skip flag, since I can be confident that the mouse events will all be sent such that the action will be fired a second time (and, therefore, I want it to be skipped).
This all seems to work, but it also seems insane. This
can't be how the JavaFX designers expected me to use the touch screen, by fighting with its dual behavior of sending touch events and mouse events. In this context, I'd rather just have the touch screen stop sending mouse events entirely. Or, as I started out, I would be happy if it just sent the pressed events for both mouse and touch like it does for touch: when, in fact, it is pressed. But it doesn't.
Is this really how touch screens work in Java?
(Adding this
thread to JavaFX, since that's become a big part of the discussion.)