Why does TabPane.tabs give jfxsc.Tabs not sfxsc.Tabs?

24 views
Skip to first unread message

Tony Sloane

unread,
May 22, 2020, 8:32:05 PM5/22/20
to ScalaFX Users
Is there a reason why the API for TabPane has different underlying tab types for the tabs accessor and the tabs update? E.g., in 14-R19:

def tabs: ObservableList[javafx.scene.control.Tab]

def tabs_=(tabSeq: Seq[Tab]): Unit

I'm finding this inconvenient since the jfx ones from the accessor leak out into my Scala code when it would be a lot more convenient to get sfx ones like I put in.

Or am I missing some better way to access the current tabs in a tabPane that keeps me in the Scala world?

thanks,
Tony


Jarek

unread,
May 22, 2020, 9:48:31 PM5/22/20
to ScalaFX Users

Tony,

tabs is intended to be used as ScalaFX ObservableBuffer, so can be modified directly. But the current code does not provide type annotation, so it may not be obvious. I added this as an issue in the repo (#324).

Since you can manipulate tabs as a collection, the assignment was probably added to make it easier to reassign compete content of tabs from a Scala collection.

Can you provide a snippet illustrating your use case of tabs to better understand what you are trying to do?

Jarek

Tony Sloane

unread,
May 25, 2020, 1:06:37 AM5/25/20
to ScalaFX Users
Jarek,

Thanks for your response. I think my primary inconvenience is when trying to iterate through the tabs.

E.g., I have a scheme where the userData of a tab stores a domain object. (This seems easier than having a separate collection that maps tabs to domain objects and vice versa.) Sometimes I have a domain object and want to find the tab that is associated with that object. Here's a simplified example where the domain object is a Component.

  import javafx.scene.control.{Tab => JavaFXTab}

  def componentTab(component : Component) : Option[JavaFXTab] =
    tabPane.tabs.find(_.userData == component)

Since tabPane.tabs is a collection of JavaFX Tabs, componentTab gives me back (an optional) one of those, instead of a ScalaFX Tab.

One follow-on consequence seems to be that once I'm in the JavaFX world I am stuck there. E.g., accesses of the content of the tab I get back from componentTab doesn't give me a ScalaFX object but a JavaFX one.

thanks,
Tony

Jarek Sacha

unread,
May 25, 2020, 12:08:36 PM5/25/20
to scalaf...@googlegroups.com

On Mon, May 25, 2020 at 1:06 AM Tony Sloane inky...@gmail.com wrote:


  import javafx.scene.control.{Tab => JavaFXTab}

  def componentTab(component : Component) : Option[JavaFXTab] =
    tabPane.tabs.find(_.userData == component)

Since tabPane.tabs is a collection of JavaFX Tabs, componentTab gives me back (an optional) one of those, instead of a ScalaFX Tab.

One follow-on consequence seems to be that once I'm in the JavaFX world I am stuck there. E.g., accesses of the content of the tab I get back from componentTab doesn't give me a ScalaFX object but a JavaFX one.

Automatic type conversions (implicit conversions) only change the external type. In this case from tabs is converted from jfx.ObservableLIst[jfx.Tab] to ObservableBuffer[jfx.Tab]. Inner type is unchanged. You need to manually handle inner type conversion, when needed. When converting from JavaFX to ScalaFX just use ScalaFX constructor, like new Tab(jfxTab), that wraps JavaFX object. In your case, map to ScalaFX type:

import scalafx.scene.control.Tab

def componentTab(component : Component) : Option[Tab] =
    tabPane.tabs.find(_.userData == component).map(new Tab(_))

When forcing “conversion” from ScalaFX to JavaFX you just access the wrapped JavaFX object using .delegate

Jarek

Tony Sloane

unread,
May 25, 2020, 6:16:37 PM5/25/20
to ScalaFX Users
Yes, I suppose I can make a new ScalaFX tab when accessing a tab in this way. But it seems wasteful to make a new object each time, when I had created a ScalaFX tab in the first place.

Tony

Reply all
Reply to author
Forward
0 new messages