実現したいこと
現在JavaFXでドロー系アプリを開発しています。
ScrollPane配下にgetContentでVBoxを設定しそのさらに配下にTextFieldを設定していますが文字がぼやけています。調べてみるとJavaFXのバグだそうですが、stackoverflowなどでは解決策として、ScrollPaneの配下のviewportをSetCache(false)にすると解決するようですが、そもそもJava上でviewpointを取得できません。
ぼやけを解消する良い考え方がありましたら教えてください。
発生している問題・分からないこと
ScrollPane配下ではないTextFieldはぼやけないが(図のA、B)、ScrollPane配下だとぼやける(図のC)。
【参考】
https://stackoverflow.com/questions/26098295/scrollpane-content-becomes-blurry-after-dragging
エラーメッセージ
error
1特にメッセージはありません。
該当のソースコード
SampleFX11controller.java
Java
1package application; 2 3import java.net.URL; 4import java.util.ResourceBundle; 5 6import javafx.collections.FXCollections; 7import javafx.collections.ListChangeListener; 8import javafx.collections.ObservableList; 9import javafx.fxml.FXML; 10import javafx.scene.control.MenuItem; 11import javafx.scene.control.ScrollPane; 12import javafx.scene.control.TextField; 13import javafx.scene.input.MouseButton; 14import javafx.scene.layout.AnchorPane; 15import javafx.scene.layout.BorderPane; 16import javafx.scene.layout.Pane; 17import javafx.scene.layout.Region; 18import javafx.scene.layout.VBox; 19 20public class SampleFX11controller { 21 22 23 final ObservableList<ScrollPane> aryScl = FXCollections.observableArrayList(); 24 25 @FXML 26 private ResourceBundle resources; 27 28 @FXML 29 private URL location; 30 31 @FXML 32 private MenuItem Menu_File_New; 33 34 @FXML 35 private BorderPane root; 36 37 @FXML 38 void initialize() { 39 assert Menu_File_New != null : "fx:id=\"Menu_File_New\" was not injected: check your FXML file 'SampleFX11.fxml'."; 40 assert root != null : "fx:id=\"root\" was not injected: check your FXML file 'SampleFX11.fxml'."; 41 42 //メニュー File -> New でScrollPaneとその上にAnchorPaneを生成。 43 Menu_File_New.setOnAction(e -> { 44 createBase(); 45 }); 46 47 //ScrollPaneの追加を監視して追加の都度setCache(False)を試みたが上手くいかない。 48 //System.out.println(aryScl.size()+" : "+scpn.lookup(".viewport")); => 件数 : 常にnull 49 //System.out.println("getChildrenUnmodifiable : "+scpn.getChildrenUnmodifiable().size()); => 常に0件 50 aryScl.addListener((ListChangeListener<ScrollPane>) change -> { 51 ScrollPane scpn = (ScrollPane)aryScl.get(aryScl.size() - 1); 52 System.out.println(aryScl.size()+" : "+scpn.lookup(".viewport")); 53 System.out.println("getChildrenUnmodifiable : "+scpn.getChildrenUnmodifiable().size()); 54 if(scpn.lookup(".viewport") != null) { 55 scpn.lookup(".viewport").setCache(false); 56 } 57 }); 58 59 } 60 61 //ここででScrollPaneとその上にAnchorPaneを生成。 62 void createBase() { 63 //一つ目のScrollPane(メニュー選択から動的に生成)。 64 ScrollPane base_sp = new ScrollPane(); 65 base_sp.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE); 66 base_sp.setPrefSize(550, 450); 67 base_sp.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE); 68 base_sp.setLayoutX(0); 69 base_sp.setLayoutY(50); 70 root.setCenter(base_sp); 71 aryScl.add(base_sp); //配列arySclにScrollPaneを追加。 72 73 AnchorPane ap = new AnchorPane(); 74 ap.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE); 75 ap.setPrefSize(1100, 900); 76 ap.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE); 77 ap.setStyle("-fx-background-color:white;"); 78 base_sp.setContent(ap); 79 80 //ctrl + マウスクリックで図のBOXを何個も生成。 81 ap.setOnMouseClicked(e -> { 82 if (e.getButton() == MouseButton.PRIMARY && e.isControlDown()) { 83 createBox(ap, e.getX(), e.getY()); 84 } 85 }); 86 } 87 88 void createBox(AnchorPane a, double x, double y) { 89 90 Pane box_p = new Pane(); 91 box_p.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE); 92 box_p.setPrefSize(80, 80); 93 box_p.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE); 94 box_p.setStyle("-fx-background-color:rgb(226, 241, 219);"); 95 box_p.setLayoutX(x); 96 box_p.setLayoutY(y); 97 a.getChildren().add(box_p); 98 99 TextField tx1 = new TextField(); 100 tx1.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE); 101 tx1.setPrefSize(80, 18); 102 tx1.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE); 103 tx1.setStyle("-fx-background-color:transparent;"); 104 tx1.setText("TestA"); 105 tx1.setLayoutX(0); 106 tx1.setLayoutY(0); 107 108 VBox vb1 = new VBox(); 109 vb1.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE); 110 vb1.setPrefSize(80, 18); 111 vb1.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE); 112 vb1.getStyleClass().add("vb"); 113 vb1.setLayoutX(0); 114 vb1.setLayoutY(20); 115 116 TextField tx2 = new TextField(); 117 tx2.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE); 118 tx2.setPrefSize(80, 18); 119 tx2.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE); 120 tx2.setStyle("-fx-background-color:transparent;"); 121 tx2.setText("TestB"); 122 tx2.setLayoutX(0); 123 tx2.setLayoutY(0); 124 vb1.getChildren().add(tx2); 125 126 //複数のScrollPaneを動的に生成。 127 ScrollPane box_sp = new ScrollPane(); 128 box_sp.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE); 129 box_sp.setPrefSize(80, 40); 130 box_sp.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE); 131 box_sp.getStyleClass().add("bs"); 132 box_sp.setLayoutX(0); 133 box_sp.setLayoutY(40); 134 135 VBox vb2 = new VBox(); 136 vb2.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE); 137 vb2.setPrefSize(80, 18); 138 vb2.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE); 139 vb2.setStyle("-fx-background-color:transparent;"); 140 vb2.setLayoutX(0); 141 vb2.setLayoutY(0); 142 box_sp.setContent(vb2); 143 144 TextField tx3 = new TextField(); 145 tx3.setMinSize(Region.USE_PREF_SIZE, Region.USE_PREF_SIZE); 146 tx3.setPrefSize(80, 18); 147 tx3.setMaxSize(Region.USE_COMPUTED_SIZE, Region.USE_COMPUTED_SIZE); 148 tx3.setStyle("-fx-background-color:transparent;"); 149 tx3.setText("TestC"); 150 tx3.setLayoutX(0); 151 tx3.setLayoutY(0); 152 vb2.getChildren().add(tx3); 153 154 box_p.getChildren().addAll(tx1, vb1, box_sp); 155 aryScl.add(box_sp); //配列arySclにScrollPaneを追加。 156 157 } 158 159}
###Main.java
java
1package application; 2 3import javafx.application.Application; 4import javafx.fxml.FXMLLoader; 5import javafx.scene.Scene; 6import javafx.scene.layout.BorderPane; 7import javafx.stage.Stage; 8 9public class Main extends Application { 10 @Override 11 public void start(Stage primaryStage) { 12 try { 13 BorderPane root = (BorderPane)FXMLLoader.load(getClass().getResource("SampleFX11.fxml")); 14 Scene scene = new Scene(root, 680, 400); 15 FXMLLoader loader = new FXMLLoader(this.getClass().getResource("Trial001.fxml")); 16 loader.setController(new SampleFX11controller()); 17 scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm()); 18 primaryStage.setTitle("SampleFX11"); 19 primaryStage.setScene(scene); 20 primaryStage.show(); 21 } catch (Exception e) { 22 e.printStackTrace(); 23 } 24 } 25 26 public static void main(String[] args) { 27 launch(args); 28 } 29}
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
⇒ リストarySclでスクロールペインの追加を監視してsetCache(False)を試みたがダメだった。
- 知人に聞いた
- その他
上記の詳細・結果
viewportがJava上で取得できないし、そもそもviewportをsetCache(false)にすることが解決策かもわからない。
補足
Liberica Standard JDK 21.0.6+10 x86 64 for Windows
※)JavaFXが同梱されている。
Windows11

回答2件
あなたの回答
tips
プレビュー