how to properly detect which mouse buttons are down in JavaFX - mouseevent

I've set a listener to my Pane so that it will detect mouse left and right buttons being down.
But when I hold left mouse button, then press right one, previous action seem to lose it's effect!
My code:
root.setOnMouseDragged(new EventHandler<MouseEvent>(){
#Override
public void handle(MouseEvent t) {
if(t.getButton() == MouseButton.PRIMARY) f1();
if(t.getButton() == MouseButton.SECONDARY) f2();
}
});
while holding LMB I have f1() running, but when I push RMB it seems like new event totally overwrites previous one: only f2() runs.
How can I separate this two events?

getButton() can return only one value at a time. And it's latest pressed button. If you need to detect multiple mouse down being pressed you need to use corresponding functions:
root.setOnMouseDragged(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent t) {
if (t.isPrimaryButtonDown()) {
System.out.println("rockets armed");
}
if (t.isSecondaryButtonDown()) {
System.out.println("autoaim engaged");
}
}
});

Related

How can I load - inflate items to a Recycler view without locking the UI or showing a load icon?

I just want to be able to display a list of contacts (without even communicating to a server) just the way it is displayed on the "Contacts" native app on the phone.
I have like 1500 contacts and when I try to load the recycler view, all items at once, it lags a lot 2 - 3 seconds.
I've achieved loading more items but with a loading bar and thats not what I want.
I've already tried Threads, Executors, postOnUIThread(), handler.post() and even AsyncTask -> Override -> doOnBackground. Nothing works.
private class CustomTask extends AsyncTask<Void, Void, Void> {
int inserted;
#Override
protected Void doInBackground(Void... param) {
//Do some work
try {
lcf.getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
((BaseActivity) lcf.getActivity()).showProgressDialog();
}
});
int currentSize = contactsLoaded.size();
for (inserted = 0; inserted < lcf.getController().getContacts().size() && contactsLoaded.size() < lcf.getController().getContacts().size(); inserted++) {
contactsLoaded.add(lcf.getController().getContacts().get(currentSize + inserted));
notifyItemRangeInserted(contactsLoaded.size() - 1, inserted);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(Void param) {
//Print Toast or open dialog
//notifyItemRangeInserted(contactsLoaded.size() - 1, 0);
if(!lcf.getController().isSelectedAffiliated()){
lcf.disclaimerLayout.setVisibility(View.VISIBLE);
}else{
lcf.disclaimerLayout.setVisibility(View.GONE);
}
lcf.isLoading=false;
((BaseActivity) lcf.getActivity()).hideProgressDialog();
}
}
That code lives within my adapter, "lcf" is a reference to the fragment. If I use the already loaded list saved on the controller (that I get from the fragment reference) and then just call notifyDataSetChanged() it LAGS like hell. So with this CustomTask I tried to load every item and notify it one by one to a Background task hoping it would make the items pop up quickly and sequentially without interfereing with the UI thread to not freeze the screen. It doesn't work. I am out of options now. I've tried everything.

How to click a View which is visible behind a RecyclerView's invisible ViewHolder item?

I have a full screen RecyclerView which will have one invisible ViewHolder Item, like below
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
....
if (position == 6) {
viewHolder.itemView.setMinimumHeight(Resources.getSystem().getDisplayMetrics().heightPixels);
viewHolder.itemView.setVisibility(View.GONE);
viewHolder.setIsRecyclable(false);
}
...
}
Once the position 6 shows up on the screen, I can see the ImageView behind it and I'd like to be able to click on that. I have added an event handler to that ImageView but it is not being triggered. It seems RecyclerView is preventing the click event to bubble down. Is there any way to click a View thru invisible/gone RecyclerView ViewItem?
Since I asked the question, I have tried multiple techniques/methods which could/should pass the click/tap event down to the view hierarchy but nothing worked. The feature I was trying to build in the app was very complex and the app itself became very complicated overtime. Too many views on top of each other and global event handlers made the implementation harder.
So I have decided as last resort that to have an empty/transparent view holder in the RecyclerView which listens the click and touch events and based on the coordinates of the touch event, I fire different action. Here is the code:
private float[] lastTouchDownXY = new float[2];
public MyView getMyView(final Context context) {
MyView view = new MyView(context);
view.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
lastTouchDownXY[0] = motionEvent.getRawX();
lastTouchDownXY[1] = motionEvent.getRawY();
}
return false;
}
});
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final float x = lastTouchDownXY[0];
final float y = lastTouchDownXY[1];
int[] mLocButton = new int[2];
// mButton is the button in the background and visible thru transparent viewholder
mButton.getLocationOnScreen(mLocButton);
final int left = mLocButton[0];
final int top = mLocButton[1];
if (x > (left - mOffset) && x < (left + mOffset + mButtonWidth) &&
y > (top - mOffset) && y < (top + mOffset + mMuteUnmuteButtonHeight)) {
// mButton clicked
} else {
// entire view clicked except mButton clickable area
}
}
});
return view;
}

mistake with finish an activity in android

I have a main activity with 6 buttons. Every button starts a new activity.
The program worked well but after that I changed some graphical attributes and made some changes in the theme a mistake occurred . I should press back button 3 times to return from an activity or exit from the main activity. Any suggestions?
btn_weeks.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
Intent i = new Intent(MainActivity.this, Weeks.class);
startActivity(i);
return false;
}
});
Buttons should implements View.OnClickListener and not OnTouchListener.

smartgwt position of mouse event

I'm trying to position a context menu in a Smart GWT Canvas, by using
`
addRecordClickHandler(new RecordClickHandler() {
public void onRecordClick(RecordClickEvent event) {
getContextMenu.setRect(rect)
getContextMenu().show();
}
});
`
The problem is that theres doesn't seem to be a straightforward way to get the X/Y coordinates of my mouse click event, which I can use to create the rect. I can get the AbsoluteTop & absoluteLeft of the enclosing Canvas, but that doesn't help me position the context menu window accurately.
RecordClickEvents are usually used with ListGrids. With a Canvas you can use ClickEvent, which has getX() and getY() methods.
addClickHandler(new ClickHandler() {
#Override
public void onClick(ClickEvent event) {
int x = event.getX();
int y = event.getY();
}
});

CF keyDown event (timed)

I need an event for my CF application, that would trigger after user has pressed an held his finger on the control for 2 seconds. What event can i use, since keyDown event is already used.
Well, KeyDown is pretty irrelevant for capturing the length of time a finger is pressed. The use of the finger relates to the events Click, MouseDown, MouseUp and MouseMove.
To get the behaviour you're after, the events you should be interested in are MouseDown and MouseUp.
I suggest the best way to do this would be to create your own control base class. Here's one I made earlier (not tested, but should give you a general idea of what to do):
public partial class BaseControl : UserControl
{
public BaseControl()
{
InitializeComponent();
base.MouseDown += new MouseEventHandler(BaseControl_MouseDown);
base.MouseUp += new MouseEventHandler(BaseControl_MouseUp);
MouseHeldTimer = new Timer();
MouseHeldTimer.Interval = 2000;
MouseHeldTimer.Tick += new EventHandler(mouseHeldTimer_Tick);
}
protected Timer MouseHeldTimer;
protected bool MouseIsDown;
void mouseHeldTimer_Tick(object sender, EventArgs e)
{
this.MouseHeldTimer.Enabled = false;
if (this.MouseHeldDown != null)
{
this.MouseHeldDown(sender, e);
}
}
void BaseControl_MouseDown(object sender, MouseEventArgs e)
{
this.MouseHeldTimer.Enabled = true;
}
void BaseControl_MouseUp(object sender, MouseEventArgs e)
{
this.MouseHeldTimer.Enabled = false;
}
public event MouseHeldDownHandler MouseHeldDown;
public delegate void MouseHeldDownHandler(object sender, EventArgs e);
}
Basically, the MouseHeldTimer will start with an interval of 2 seconds the moment the user touches their finger to the screen. If the user lifts their finger the timer is stopped. If the user's finger is down for longer than 2 seconds, the delegate event MouseHeldDown will fire. You can then capture this event on your form by doing the following:
control.MouseHeldDown+= new EventHandler(control_MouseHeldDown);
Alternatively, if you only care about the form, you can just use the Form's DoubleClick event as that will fire after holding the mouse down for a second or two.