質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • JavaFX

    397questions

    JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。

データバーのようなTableCell

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 593

oscikonome

score 9

Excelのデータバー(以下参照)のような表示をTableViewで実装したいです。
http://www.becoolusers.com/excel/data-bar.html

そこで、TableColumを以下のようにしてみましたが
・テキストとデータバーを一緒に表示できない
・TableColumnの幅を変更してもデータバーの幅が追従しない
という問題に直面しています。

解決方法についてどうかよろしくお願いいたします。

(TableColumn).setCellFactory(tableColumn  -> new TableCell<Sample, Double>() {
//HBoxを配置し、その幅でバーを表したい
private HBox box = new HBox();
{
double width = (TableColumn).getWidth();//項目の最大幅を取得
double rate = 0.6;//データバーの表示割合(今回は60%で固定、本来はこのカラムに設定されたDoubleを用いたい)
box.setMaxWidth(width * rate);//幅設定
}
@Override
protected void updateItem(Double value, boolean empty) {
super.updateItem(value, empty);
setText(null);
if (value == null || empty) {
setGraphic(null);
} else {
box.setBackground(new Background(new BackgroundFill(value, null, null)));
setGraphic(box);//データバーを表示したい
setText("60%");//テキストを表示したい、本来はDoubleの値を使用
}
}
});

*その後

回答を参考に、以下のようにしておおよその実装はできましたが、まだうまくいっていない点があります。
・カラム幅を変更しないとデータバーが表示されない。(初期描画時点ではデータバーが表示されず)
・カラム幅を画面幅まで広げたあと縮めると、少し広げても30の数字が表示されない。(画面幅まで広げないと表示されない)
・カラム幅を変更してからスクロールすると、一部データバーの長さがおかしい。(カラム幅を変更するとなおる)
いずれも幅変更とスクロールで解決する表示の問題ですが、都度変更しなくてもきれいに表示されるようにすることは可能でしょうか。

よろしくお願いいたします。

import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;

public class Main extends Application {
@Override
public void start(Stage primaryStage) {
TableView<DataClass> table = new TableView<DataClass>();
TableColumn<DataClass, Integer> column = new TableColumn<DataClass, Integer>("VALUE");
column.setCellValueFactory(feature -> feature.getValue().getValue().asObject());
column.setPrefWidth(200);
column.setCellFactory(tableColumn -> new TableCell<DataClass, Integer>() {
private AnchorPane pane = new AnchorPane();    //セルに画像として表示するベース
private AnchorPane barArea = new AnchorPane();    //バー領域
private Rectangle bar = new Rectangle();    //バー
private Label label = new Label();    //テキスト領域
{
//label.setPadding(new Insets(3));
barArea.getChildren().addAll(bar);
pane.getChildren().addAll(barArea, label);
AnchorPane.setRightAnchor(label, 0.0);
AnchorPane.setLeftAnchor(barArea, 0.0);
AnchorPane.setRightAnchor(barArea, 30.0);    //右30はテキスト領域として固定で空けておく
}
public void updateItem(Integer value, boolean empty) {
super.updateItem(value, empty);
if (value == null || empty) {
setText(null);
} else {
bar.setWidth(barArea.getWidth() * value/30);    //幅設定
column.widthProperty().addListener((self, old, val) -> {    //幅の変更に合わせてデータバーも変更
bar.setWidth(barArea.getWidth() * value/30);    //幅設定
});
bar.setHeight(16);    //データバーの高さ
bar.setFill(Paint.valueOf("#8f8f8f8f"));
label.setText(Integer.toString(value));    //ラベルに文字列をセット
label.setStyle("-fx-alignment: center-right;");    //文字列ラベルを右寄せ
setGraphic(pane);
setText(null);
}
}
});
table.getColumns().add(column);
ObservableList<DataClass> dataClassList = FXCollections.observableArrayList();
for (int i = 0; i <= 30; i++){
DataClass data = new DataClass(i);
dataClassList.add(data);
}
table.setItems(dataClassList);
Scene scene = new Scene(table,400,400);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}

class DataClass{    //データクラス
private IntegerProperty value = new SimpleIntegerProperty();
public DataClass(int value){
setValue(value);
}
public IntegerProperty getValue() {
return value;
}
public void setValue(int value) {
this.value.set(value);
}
}

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

テキストとデータバーを一緒に表示できない

CellのgraphicプロパティーとtextプロパティーはHBoxでレイアウトされるように(つまり重ならないように意図されて)設計されてますのでそうなります。重なるようにするにはtextプロパティーを使わずにバーとテキストをStackPaneやAnchorPaneなどを使って自前のノード階層にするかCellのbackgroundプロパティーでデータバーを表現するようにするとそれらしくできると思います。

TableColumnの幅を変更してもデータバーの幅が追従しない

JavaFXではほぼすべてのvisual属性がobservableなプロパティーになってますのでbindしたりChangeListenerを使うと別の値に追従させることができます。Cellは特定の行・列位置に固定的に結びつかないのでupdateItemの度にbind/ChangeListenerの再設定をするよう配慮しないといけませんが、それさえできれば追従させること自体は可能です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/03/19 17:41

    column.widthProperty().addListenerの部分をbindにしたらうまくいきました

    キャンセル

  • 2017/03/19 18:15

    うーん…bindでうまく動いてChangeListenerでうまくいかなくということでしたか…
    レイアウトを制御するコードは難しいですね。JavaFXのレイアウト方式にさからわないように作れさえすればたいがいはあっさり動くのですが「JavaFXのレイアウトポリシーに反することをしている」のに気づけないとドツボにはまって抜けられなくなるのはよく経験します。自分はScrollPaneやImageViewなどがとても難しく感じます。何度もはまりましたし、いまだに使いこなせてません><

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • JavaFX

    397questions

    JavaFXとは、Java仮想マシン上で動作するリッチインターネットアプリケーション (RIA) のGUIライブラリです。Swingとは異なり、FXMLと呼ばれる XMLとCSSを併用してデザインを記述します。