回答編集履歴

2 誤記

KSwordOfHaste

KSwordOfHaste score 18118

2017/01/08 22:12  投稿

> 自動的にどんどんCellが追加されるので見たいツイートが流れていってしまいます。
とのことですが、特別な制御をせずTableViewがもっているスクロール機能をそのまま利用すると(つまり別途ScrollPaneを用意してその上にTableViewを載せたりしないでという意味)テーブルのitemsプロパティーへ要素を追加しても行が流れていくといった動きにはならず位置はほぼ固定になると思います。追加に伴いドット単位でずれたりはしますが、それでも操作の邪魔になるほど極端にはずれないと思います。
どのような制御をしているのかもう少し詳しく説明したほうがよいと思います。
---
追記:
要素を上に追記しているということですので2つほどアイデアをコメントします。
要素を上に追加しているということですので2つほどアイデアをコメントします。
1. 簡単な方法
セルを選択、あるいは別途設けたトグルボタンなどで「メッセージのリアルタイムな表示を保留するモード」を作ると一番簡単にできそうです。追記をやめるので表示されているメッセージから望みのものを探したり選択したりする操作がじゃまされません。UI仕様上はイマイチな感じではありますが実装が簡単です。もしこうするなら保留中に新たにツィートされたらどこかに「1件のツィートを表示保留中」なんて点滅させてやれば保留解除を忘れたりといったことはなくなると思います。
2. ちょっと面倒な方法
要素を先頭に追記していく方式だとどうしてもビューポートの位置はずれると思います。TableViewの動きを観察した限りでは、要素数が変化した際のスクロールの制御を「ビューポートが先頭から何要素目からの表示となっているかを保存する」としているようです。ですので、その戦略を変えてやる必要があります。具体的には自分でスクロールバーのvalueプロパティーの値を再計算する必要があると思います。
2.の方法は自分はすぐにはわからなかったので少し調べてみました。
ツィートなので各要素の高さはまちまちだと思います。だとすると何要素追加したかで単純にScrollBarのvalueの値を計算できません。リファレンスからscrollTo(itemIndex)みたいなものを期待して探してみたのですが見つかりませんでした(見落としがあるかも知れませんが)。
そこでSkinの中にScrollBarがあるならviewportBoundsを利用すると考えskin階層を調べてみました。しかし以下の通りありませんでした。
```
Skin(TableView)
+com.sun.javafx.scene.control.skin.TableHeaderRow
|+javafx.scene.layout.Region
|+com.sun.javafx.scene.control.skin.NestedTableColumnHeader
||+javafx.scene.layout.StackPane
|+javafx.scene.layout.StackPane
||+javafx.scene.control.Label
+com.sun.javafx.scene.control.skin.VirtualFlow
|+com.sun.javafx.scene.control.skin.VirtualFlow.ClippedContainer
||+javafx.scene.Group
||javafx.scene.Group
|+com.sun.javafx.scene.control.skin.VirtualScrollBar
|+com.sun.javafx.scene.control.skin.VirtualScrollBar
|+javafx.scene.layout.StackPane
+javafx.scene.layout.Region
+javafx.scene.layout.Region
```
ここまで調べた限り自分の知識の範囲内だと上記の階層の実装の中に使えそうなものがないか調べるか、TableCellのジオメトリーから各要素の高さを求めそれをどこかへキャッシュしておいて、それに基づいて前高および先頭アイテム位置から目的の行までの高さを計算してvalueを求めるなどの工夫をしないといけないように思いました。
残念ながらTableViewについてこういう目的で中身を調べたことがないので具体的なアドバイスはできそうもないです。操作感からいえば2.の方がよいのだろうとは思いますが自分なら1で妥協しそうです。
1 追記

KSwordOfHaste

KSwordOfHaste score 18118

2017/01/08 22:10  投稿

> 自動的にどんどんCellが追加されるので見たいツイートが流れていってしまいます。
とのことですが、特別な制御をせずTableViewがもっているスクロール機能をそのまま利用すると(つまり別途ScrollPaneを用意してその上にTableViewを載せたりしないでという意味)テーブルのitemsプロパティーへ要素を追加しても行が流れていくといった動きにはならず位置はほぼ固定になると思います。追加に伴いドット単位でずれたりはしますが、それでも操作の邪魔になるほど極端にはずれないと思います。
どのような制御をしているのかもう少し詳しく説明したほうがよいと思います。
どのような制御をしているのかもう少し詳しく説明したほうがよいと思います。
---
追記:
要素を上に追記しているということですので2つほどアイデアをコメントします。
1. 簡単な方法
セルを選択、あるいは別途設けたトグルボタンなどで「メッセージのリアルタイムな表示を保留するモード」を作ると一番簡単にできそうです。追記をやめるので表示されているメッセージから望みのものを探したり選択したりする操作がじゃまされません。UI仕様上はイマイチな感じではありますが実装が簡単です。もしこうするなら保留中に新たにツィートされたらどこかに「1件のツィートを表示保留中」なんて点滅させてやれば保留解除を忘れたりといったことはなくなると思います。
2. ちょっと面倒な方法
要素を先頭に追記していく方式だとどうしてもビューポートの位置はずれると思います。TableViewの動きを観察した限りでは、要素数が変化した際のスクロールの制御を「ビューポートが先頭から何要素目からの表示となっているかを保存する」としているようです。ですので、その戦略を変えてやる必要があります。具体的には自分でスクロールバーのvalueプロパティーの値を再計算する必要があると思います。
2.の方法は自分はすぐにはわからなかったので少し調べてみました。
ツィートなので各要素の高さはまちまちだと思います。だとすると何要素追加したかで単純にScrollBarのvalueの値を計算できません。リファレンスからscrollTo(itemIndex)みたいなものを期待して探してみたのですが見つかりませんでした(見落としがあるかも知れませんが)。
そこでSkinの中にScrollBarがあるならviewportBoundsを利用すると考えskin階層を調べてみました。しかし以下の通りありませんでした。
```
Skin(TableView)
+com.sun.javafx.scene.control.skin.TableHeaderRow
|+javafx.scene.layout.Region
|+com.sun.javafx.scene.control.skin.NestedTableColumnHeader
||+javafx.scene.layout.StackPane
|+javafx.scene.layout.StackPane
||+javafx.scene.control.Label
+com.sun.javafx.scene.control.skin.VirtualFlow
|+com.sun.javafx.scene.control.skin.VirtualFlow.ClippedContainer
||+javafx.scene.Group
||javafx.scene.Group
|+com.sun.javafx.scene.control.skin.VirtualScrollBar
|+com.sun.javafx.scene.control.skin.VirtualScrollBar
|+javafx.scene.layout.StackPane
+javafx.scene.layout.Region
+javafx.scene.layout.Region
```
ここまで調べた限り自分の知識の範囲内だと上記の階層の実装の中に使えそうなものがないか調べるか、TableCellのジオメトリーから各要素の高さを求めそれをどこかへキャッシュしておいて、それに基づいて前高および先頭アイテム位置から目的の行までの高さを計算してvalueを求めるなどの工夫をしないといけないように思いました。
残念ながらTableViewについてこういう目的で中身を調べたことがないので具体的なアドバイスはできそうもないです。操作感からいえば2.の方がよいのだろうとは思いますが自分なら1で妥協しそうです。

思考するエンジニアのためのQ&Aサイト「teratail」について詳しく知る