B4J Question [SOLVED] B4XDialog - default button

LucaMs

Expert
Licensed User
Longtime User
(Most likely this should be a "wish").

How to set a default button (one of the three) so that its click event fires when Enter is pressed?

Note that I tried:
B4X:
xDialog.GetButton(xui.DialogResponse_Cancel).As(Button).RequestFocus
but it doesn't seem to work.


EDIT - I found a way, to improve (make it general routines):
B4X:
    Dim r As Reflector
    r.Target = xDialog.GetButton(xui.DialogResponse_Cancel).As(Button)
    r.AddEventFilter("DlgBtn", "javafx.scene.input.KeyEvent.KEY_PRESSED")
    r.AddEventFilter("DlgBtn", "javafx.scene.input.KeyEvent.KEY_RELEASED")

B4X:
Sub DlgBtn_Filter (EventData As Event)
    Dim jo As JavaObject = EventData
    Dim Code As String = jo.RunMethod("getCode", Null)
    Dim EventType As String = jo.RunMethod("getEventType", Null)
    Log(Code)
    Log(EventType)
End Sub
 
Last edited:
Solution
For me using jdk1.8.0_271 this works as expected.
B4X:
    Dialog.Title = "Test"
    Dim RS As ResumableSub = Dialog.Show("Test","OK","No","Cancel")
    Dialog.GetButton(xui.DialogResponse_Cancel).As(JavaObject).RunMethod("setCancelButton",Array(True))
    Dialog.GetButton(xui.DialogResponse_Positive).As(JavaObject).RunMethod("setDefaultButton",Array(True))
    Wait For(RS) Complete(Resp As Int)
    Log(Resp)

But java jdk-11.0.1 requires:

B4X:
    Dialog.Title = "Test"
    Dim RS As ResumableSub = Dialog.Show("Test","OK","No","Cancel")
    Dialog.GetButton(xui.DialogResponse_Cancel).As(JavaObject).RunMethod("setCancelButton",Array(True))
    Dialog.GetButton(xui.DialogResponse_Positive).RequestFocus
    Wait For(RS) Complete(Resp As...

LucaMs

Expert
Licensed User
Longtime User
(Most likely this should be a "wish").

How to set a default button (one of the three) so that its click event fires when Enter is pressed?

Note that I tried:
B4X:
xDialog.GetButton(xui.DialogResponse_Cancel).As(Button).RequestFocus
but it doesn't seem to work.


EDIT - I found a way, to improve (make it general routines):
B4X:
    Dim r As Reflector
    r.Target = xDialog.GetButton(xui.DialogResponse_Cancel).As(Button)
    r.AddEventFilter("DlgBtn", "javafx.scene.input.KeyEvent.KEY_PRESSED")
    r.AddEventFilter("DlgBtn", "javafx.scene.input.KeyEvent.KEY_RELEASED")

B4X:
Sub DlgBtn_Filter (EventData As Event)
    Dim jo As JavaObject = EventData
    Dim Code As String = jo.RunMethod("getCode", Null)
    Dim EventType As String = jo.RunMethod("getEventType", Null)
    Log(Code)
    Log(EventType)
End Sub
No, unfortunately that code is not suitable.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
It appears to work like this:
B4X:
    Dialog.Title = "Test"
    Dim RS As ResumableSub = Dialog.Show("Test","OK","No","Cancel")
    Dialog.GetButton(xui.DialogResponse_Negative).RequestFocus
    Wait For(RS) Complete(Resp As Int)
    Log(Resp)
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
You can also set the cancel behaviour for when the escape key is pressed:

B4X:
    Dialog.Title = "Test"
    Dim RS As ResumableSub = Dialog.Show("Test","OK","No","Cancel")
    Dialog.GetButton(xui.DialogResponse_Cancel).As(JavaObject).RunMethod("setCancelButton",Array(True))
    Dialog.GetButton(xui.DialogResponse_Positive).RequestFocus
    Wait For(RS) Complete(Resp As Int)
    Log(Resp)

The request focus on the positive button will only work if there are no focusable views in the dialog (CustomDialog or template) that have been focused.
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
It appears to work like this:
B4X:
    Dialog.Title = "Test"
    Dim RS As ResumableSub = Dialog.Show("Test","OK","No","Cancel")
    Dialog.GetButton(xui.DialogResponse_Negative).RequestFocus
    Wait For(RS) Complete(Resp As Int)
    Log(Resp)
Thanks, Steve, that was the first think I tried; see the first post, and it didn't work. I'll try again.
 
Last edited:
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Thanks, Steve, that was the first think I tried; see the first post, and it didn't work. I'll try again.
No, it does not work "here". I have (and had):
B4X:
        Dim sf As Object = xDialog.Show(sb.ToString, "Copia", "", "OK")
        xDialog.GetButton(xui.DialogResponse_Cancel).Color = xui.Color_Blue ' just to try
        xDialog.GetButton(xui.DialogResponse_Cancel).RequestFocus
        Wait For (sf) Complete (Result As Int)
(default B4XDialog, no other views)
 
Last edited:
Upvote 0

stevel05

Expert
Licensed User
Longtime User
So what happens if you just call it normally and Press return?

B4X:
Wait For(Dialog.Show("Test","OK","No","Cancel")) Complete (Resp As Int)

For me, the form closes and returns Dialog Response Cancel (-3)
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
So what happens if you just call it normally and Press return?
Nothing, of course (?), the dialog remains on the screen. That's why I asked the question, as well as how to set which of the three buttons to make "active".


Anyway I did a test on a new empty project. In it I put a TextField and a Button, in order, so that the TextField definitely has focus, at startup.
I put a Sleep(1000) and then Button1.RequestFocus (Button1 is declared as B4XView).
The focus is on Button1, you can see it, but pressing Enter the Button1_Click event does not trigger.

[It's the same if you declare Button1 as Button]
 
Last edited:
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
MAYBE this is the way but for now it doesn't work.

B4X:
    Dim JO1 As JavaObject
    JO1 = Button1.As(Button)
    Dim JO2 As Object = JO1.CreateEventFromUI("javafx.event.EventHandler", "Action", Null)
    JO1.RunMethod("setOnAction", Array(JO2))

B4X:
Private Sub Button1_Action
    Log("Button1_Action")
End Sub
 
Upvote 0

Magma

Expert
Licensed User
Longtime User
Hi there, check here how i am checking for keypress at b4xdialog:

B4X:
    Private nowinpref As Boolean=False
    'Private sendk As AWTRobot
...
Private Sub B4XPage_Created (Root1 As B4XView)
...
    AddKeyPressedListener
    ...
End Sub

Sub AddKeyPressedListener
    Dim r As Reflector
    r.Target = Root'B4XPages.GetNativeParent(Root)
    #IF B4J
    r.AddEventFilter("keypressed", "javafx.scene.input.KeyEvent.ANY")
    #END IF
End Sub

Sub KeyPressed_Filter (e As Event)

        Dim jo As JavaObject = e
        Dim EventType As String = jo.RunMethodJO("getEventType", Null).RunMethod("getName", Null)
        'Log(EventType)
...
    If Dialog.Visible Then  'Here is what you want...
        Dim jo As JavaObject = e
        Dim EventType As String = jo.RunMethodJO("getEventType", Null).RunMethod("getName", Null)
        If EventType = "KEY_PRESSED" Then
            Dim keycode As String = jo.RunMethod("getCode", Null)
            If keycode = "ESCAPE" Then
                Dialog.Close(xui.DialogResponse_Cancel)
            End If
        End If
    End If


    If nowinpref=True Then
        Dim jo As JavaObject = e
        Dim EventType As String = jo.RunMethodJO("getEventType", Null).RunMethod("getName", Null)
        If EventType = "KEY_PRESSED" Then
            Dim keycode As String = jo.RunMethod("getCode", Null)
            If keycode = "ESCAPE" Then
                prefdialog.Dialog.Close(xui.DialogResponse_Cancel)
            End If
            'If keycode = "ENTER" Then
            'sendk.RobotSpecialKeyPress("TAB")
            'End If
        End If
    End If

end sub

Remember when showing b4xdialog (check dialog.visible)... so if you want enter to do something different than usual you can say it there...
If b4xpreferencesdialog - before you show nowinpref=True and when hide it / close it nowinpref=False
 
Last edited:
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
Thanks, @Magma, now this works:
B4X:
AddKeyPressedListener
    
Dialog.Initialize(Root)
Wait For (Dialog.Show("Message", "Yes", "No", "Cancel")) Complete (Result As Int)
Log("Result: " & Result)

B4X:
Private Sub AddKeyPressedListener
    Dim r As Reflector
    r.Target = Root
    #IF B4J
        r.AddEventFilter("keypressed", "javafx.scene.input.KeyEvent.ANY")
    #END IF
End Sub

Private Sub KeyPressed_Filter (e As Event)
    Dim jo As JavaObject = e
    Dim EventType As String = jo.RunMethodJO("getEventType", Null).RunMethod("getName", Null)
    
    If Dialog.Visible Then
        Dim jo As JavaObject = e
        Dim EventType As String = jo.RunMethodJO("getEventType", Null).RunMethod("getName", Null)
        If EventType = "KEY_PRESSED" Then
            Dim keycode As String = jo.RunMethod("getCode", Null)
            If keycode = "ENTER" Then
                Dialog.Close(xui.DialogResponse_Cancel)
            End If
        End If
    End If
End Sub
 
Upvote 0

LucaMs

Expert
Licensed User
Longtime User
MAYBE this is the way but for now it doesn't work.

B4X:
    Dim JO1 As JavaObject
    JO1 = Button1.As(Button)
    Dim JO2 As Object = JO1.CreateEventFromUI("javafx.event.EventHandler", "Action", Null)
    JO1.RunMethod("setOnAction", Array(JO2))

B4X:
Private Sub Button1_Action
    Log("Button1_Action")
End Sub
A curious thing:

I "accidentally" found that the Action event for the Button already exists, even though it is not listed among the available ones.
If you implement the Sub Button1_Action, however, the Button1_Click event will not fire.
 
Upvote 0
Top