B4J Question Tableview SelectedRowChanged with textfield

AHilton

Active Member
Licensed User
Longtime User
The SelectedRowChanged event isn't being fired in a tableview when a textfield (possibly other views) is being used in the cells for a column either by clicking or tabbing on the textfields. It does fire when you click or arrow around on the columns without textfields.

How do you force the event to fire?
 

EnriqueGonzalez

Well-Known Member
Licensed User
Longtime User
May be with something like this:

B4X:
private Sub txt_FocusChanged (HasFocus As Boolean)
    Dim txt As TextField = Sender
    Dim iAmInRow As Int = txt.Tag
    tw_SelectedRowChanged(iAmInRow,Null)
End Sub

private Sub tw_SelectedRowChanged(Index As Int, Row() As Object)
    Dim tw As TableView
    Row = tw.SelectedRowValues
   
End Sub
 
Upvote 0

AHilton

Active Member
Licensed User
Longtime User
Yes, that does work, Enrique, but I was hoping for a more OOP way. I really hate to keep using .Tag to pass data all over the place in these apps.

I was trying to get a reference to the selected row to change a value in one of the other columns from within a column with a textfield. I found that the SelectedRowChanged wasn't firing in order for me to get that reference on what row I was on. I tried doing a parent.parent. oop thing starting on the passed-in textfield object but that just wasn't working (I'm still hoping I'm missing something and someone will chime in with the solution). I miss the good oop and data-centric controls of Visual FoxPro during this project.

Anyway, I bypassed SelectedRowChanged altogether and just used the .Tag straight from my textfield_focuschanged event to get my row reference.

By the way, the Tableview SelectedRow property has to manually be set, as well, in the SelectedRowChanged event. It doesn't do it by itself either.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
This might help without having to use tags.
Textfield (tf) is added to the row in the first column
B4X:
Sub tf_action
Dim r As Int = 0
For Each row() As Object In tv.Items
If row(0) = Sender Then 'textfield is in col 0
Log("row " & r)
tv.SelectedRow = r
Exit
Else
  r = r + 1
End If
Next
End Sub
Sub tf_mouseclicked(eventdata As MouseEvent)
Dim r As Int = 0
For Each row() As Object In tv.Items
If row(0) = Sender Then 'textfield is in col 0
Log("row " & r)
tv.SelectedRow = r
Exit
Else
  r = r + 1
End If
Next
End Sub

It can probably be optimized by only searching in a specific table column for the item as opposed to how I search the tableview items for object(0).
Unfortunately I cba to do it :)
 
Last edited:
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Maybe something like this:
B4X:
Sub Process_Globals
    Private fx As JFX
    Private MainForm As Form
    Private TableView1 As TableView
End Sub

Sub AppStart (Form1 As Form, Args() As String)
    MainForm = Form1
    MainForm.RootPane.LoadLayout("1") 'Load the layout file. (Just contains the Tableview)
    MainForm.Show
 
    TableView1.SetColumns(Array As String("Row","Text"))
 
    Dim Items As List
    Items.Initialize
    For i = 0 To 10
        Dim L As Label
        L.Initialize("")
        Dim TF As TextField
        TF.Initialize("TF")
        TF.Text = "Row " & i
        Dim Row(2) As Object
        Row(0) = L
        Row(1) = TF
        TableView1.Items.Add(Row)
    Next
End Sub

Sub TF_MouseClicked (EventData As MouseEvent)
    Log("Clicked")
    Dim TF As TextField = Sender
    TableView1.SelectedRow = ASJO(TF.parent).RunMethodJO("getTableRow",Null).RunMethod("getIndex",Null)
' 
End Sub
'
Private Sub ASJO(JO As JavaObject) As JavaObject
    Return JO
End Sub
 
Upvote 0

AHilton

Active Member
Licensed User
Longtime User
Thanks, Daestrum, that works for me. It's not as clean as what I'd like (parent.parent etc.) but I certainly like it better than dealing with the .Tag
 
Upvote 0

AHilton

Active Member
Licensed User
Longtime User
Steve, your solution works. Thanks. Again, not what I'd like to see (oop, inheritance and all of that) in B4x, but it certainly works for my problem.

A related question for anyone: Where would an average slub, like myself, find information on those methods in your code (getTableRow, getIndex)? What I mean is, is there B4x documentation or one of the helper projects that has these kinds of references for future problems and methods for various views when we run into a wall with what B4x provides natively? Or is this something you pretty much have to know java and javafx or look it up and translate from other languages found in stackoverflow, oracle documentation, etc?
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
Using JavaObject requires a little java knowledge if you are doing something complicated, if you have the correct class you can call any of the methods available on that class. You will need to do a little reading, but it will either work of if it's not quite right, it won't. But more knowledge is always good, and it's worth digging a bit and trying things out. Erel beat me to posting the link, but look up Tableview, there are several related classes that you may need to trawl through, but you'll find the references.
 
Upvote 0

stevel05

Expert
Licensed User
Longtime User
The main issue in solving your problem in a structured way is that the Text view is consuming the mouse click. It would probably be possible to pass through the click using JavaObject, but the solution I posted is much simpler.

If you read the documentation for tableview, it is suggesting that a possibility is to use Labels to display the data (which would not then consume the click event) and change the interface to an edit text if the user double clicks on the label. There are methods available in the API to help achieve this, but again would be much more complicated to implement for this simple issue and would require the creation of a library of some description.
 
Last edited:
Upvote 0

AHilton

Active Member
Licensed User
Longtime User
"requires a little java knowledge if you are doing something complicated ..."
Like getting the row containing the view/control you're 'working' in? :confused:

I agree with you, Steve, that your solution was simpler than having to deal with passing events up/down the chain or using a non-standard interface of changing from text/labels/textfields on the fly. I'm just going to have to dig deep into javafx to get a handle on how to deal with these B4J problems as they come up.

I finally found the getTableRow method reference in your code: http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/TableCell.html#getTableRow--
and the getIndex: http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/IndexedCell.html#getIndex--
for anybody interested in the future.

It's going to take quite a bit of research into java and javafx to get some things working as the users like but that's just how this project (~2 years left) is going to work out, I guess. I've been committed to using B4x (ie All of the products before this project is done, I believe) and it looks like I'll be diving into some deeper waters that I thought, now, on the B4J side of things.
Anyway, I've hijacked my own thread.

Thanks, Steve, and everyone for the help. I'm back on track and on to the next problem (and, hopefully, something I can solve myself) ...
 
Upvote 0
Top