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

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

新規登録して質問してみよう
ただいま回答率
85.50%
JavaFX

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

Q&A

解決済

1回答

2330閲覧

データバーのようなTableCell

oscikonome

総合スコア16

JavaFX

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

0グッド

0クリップ

投稿2017/03/10 10:26

編集2017/03/15 07:15

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);
}
}

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

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

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

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

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

投稿2017/03/10 14:29

KSwordOfHaste

総合スコア18392

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oscikonome

2017/03/19 08:41

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

2017/03/19 09:15

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問