B4J Question [SOLVED] ListView: Only one event fired

JanG

Member
Licensed User
Longtime User
I have a ListView and I have to check, if the selected position has changed. If the change is done by RightMouseClick I have to do something with the data inside.

There are two events:
B4X:
Sub MyListView_SelectedIndexChanged(Index As Int)
End Sub

Sub MyListView_MouseClicked(EventData As MouseEvent)
End Sub

But in SelectedIndexChanged I can't investigate if it was raised by "RIGHT_BUTTON", because I don't have EventData. In MouseClicked I am not informed, if a selection change was done by keyboard. And if I use both events, only one is fired.

Any solution?
 

William Lancee

Well-Known Member
Licensed User
Longtime User
The following responds to right clicks and then deselects the item. Useful for showing more detail about the item.

B4X:
Sub Process_Globals
    Private SaveSelected As List
    private MyListView as ListView
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    SaveSelected = MyListView.getSelectedIndices
End Sub

Sub MyListView_MouseClicked(EventData As MouseEvent)
    Dim rightButton As Boolean = EventData.SecondaryButtonPressed
    Dim leftButton As Boolean = EventData.PrimaryButtonPressed
    If rightButton Or leftButton Then
        Dim newSelected As List = MyListView.GetSelectedIndices
        For j = 0 To newSelected.size-1
            If saveSelected.IndexOf(newSelected.Get(j)) = -1 Then
                Dim mark As String = "left  "
                If rightButton Then mark = "right"
                Dim selIndex As Int = newSelected.Get(j)
                Log(mark & " " & selIndex & " " & MyListView.Items.Get(selIndex))
                If rightButton Then
                    'turn off selection
                    newSelected.removeAt(j)
                    fieldList.SetSelectedIndices(newSelected)
                Else
                    'handle left click selection
                End If
                Exit  'don't need to look at anything else
            End If
        Next
        saveSelected = MyListView.getSelectedIndices
    End If
End Sub
 
Upvote 0

JanG

Member
Licensed User
Longtime User
Thank you for your solution! But this doesn't solve the problem. When the user changes the selected item via keyboard, I have to do something internally with my data. When the user changes the selection via mouse I have to to the same things. But if the user selects the item via right click, I habe to do other things. And there is the problem. I can use only one event. If I use the "SelectedIndexChanged", I do not know if this was triggered by left or right mouse button.

If someone (Erel e.g.) will tell that this is a limitation and it is not possible, it's okay. But it's good to know if the limitation is my knowledge or by b4j... :)
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Using the code in #2, if you add he following at the end of the key event, then the mouse event will know that the selection changed because of the mouse click.

B4X:
saveSelected = MyListView.getSelectedIndices
 
Upvote 0

JanG

Member
Licensed User
Longtime User
Sorry, I don't understand... The problem is that only one event is fired. Your example works, but if I change the selected element by keyboard, the MouseClick event is not fired. In this situation the system will not recognize that a change has happened. If I work with mouse only, no problem, but selection changes can be done by keyboard (arrow keys) also.
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Hi

If you save the selected indices after the key event, then when the click event occurs and the selected indices are different from the saved ones then the mouse is responsible for the selected change. That's it. I responded to question because I used this work around successfully. The cascade of events in java-jx is complex, and there may be another way of making both events happen, but I haven't found it. I should mention that when I right-click using the above, the action occurs after the mouse button comes up, this could be a problem in some cases. Anyway, good luck.
 
Upvote 0

JanG

Member
Licensed User
Longtime User
If you save the selected indices after the key event, then when the click event occurs and the selected indices are different from the saved ones then the mouse is responsible for the selected change.
Yes, that's true. But when I have both events, the Click event is not fired. Instead the SelectedIndexChanged event is fired and it does not show if left or right mouse button is responsible. Identifiying the mouse-button is the problem.

Maybe I should post an example... I will do it, but it will take a while...
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
You don't need both events. Just the click. The keyboard events are not related to this issue, other than to reset the savedSelected.
 
Upvote 0

JanG

Member
Licensed User
Longtime User
If I only have the click event, I can't react on selecting another element in the ListView by keyboard. It is because if you change the selection via arrow keys the click event is not fired.

I hope I can show an example for better understanding in the next few days.
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
From your response, I understand now that you don't have a key event handler. I assumed you did.
Add one. It will let you save the selected indices, so the click event will know it is responsible for the latest selection.
 
Upvote 0

William Lancee

Well-Known Member
Licensed User
Longtime User
Hi again

I thought I would try to find a simpler solution. The secret is to use the mousePressed event instead of mouseClicked event. This event happens first and bubbles up to the listView selection change event.

B4X:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private MyList As ListView
    Private saveMouseButton As String = ""
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MyList.Initialize("MyList")
    MainForm.RootPane.AddNode(MyList, 0, 0 , 300,300)
    MyList.items.add("Choice 1")
    MyList.items.add("Choice 2")
    MyList.items.add("Choice 3")
    MainForm.Show
End Sub

Sub MyList_SelectedIndexChanged(Index As Int)
    Select Case saveMouseButton
        Case "Right": Log("Right Pressed " & Index)
        Case "Left": Log("Left Pressed " & Index)
        Case "": Log("Changed by keyboard " & Index)
    End Select
    saveMouseButton = ""
End Sub

Sub MyList_MousePressed(EventData As MouseEvent)
    If EventData.SecondaryButtonPressed Then saveMouseButton = "Right"
    If EventData.PrimaryButtonPressed Then saveMouseButton = "Left"
End Sub
 
Upvote 0

JanG

Member
Licensed User
Longtime User
Thank you very much :) !!! That did the trick! Now it works as expected. Sometimes the simple solutions are more easy than one might think... ;)
 
Upvote 0
Top