私はエディタで使用されるフォントを選択できるオプション・ダイアログを含むClojureプログラムを構築しています。ちょうど他の多くのプログラムと同様に、ドロップダウンリストにフォント名をフォントで表示するComboBoxをユーザに提示したいと思います(例えば、 'Calibri'はCalibriフォントで表示され、 'Arial'はArialで表示されますon)。ClojureのJavaFXフォント・フェイス・ダイアログ
以前はJavaで、セルファクトリを使用してリスト内の各セルの外観をカスタマイズしました。
Clojureへの翻訳は機能しません。ここで
は、私がこれまでに出ているものです:
(defn build-font-list-cell
"Return a Cell with an overridden updateItem implementation for
the cells in the font list combo. Format the name of the font in
the actual font."
[]
(proxy [TextFieldListCell] []
(updateItem [^String family mt]
(proxy-super updateItem family mt)
(if mt
(.setText this nil)
(do
(.setFont this (Font/font family))
(.setText this family))))))
(defn build-font-list-cell-factory
[]
(proxy [Callback] []
(call [list-view]
(build-font-list-cell))))
(defn build-font-face-combo
"Build, configure, and return the combo box used to select the font
face for the editor."
[]
(let [family-list (FXCollections/observableArrayList (Font/getFamilies))
font-face-combo (ComboBox. family-list)
current-face @tentative-font-face]
(.setEditable font-face-combo true)
(.addListener (.selectedItemProperty (.getSelectionModel font-face-combo))
^ChangeListener (face-combo-listener font-face-combo))
(.setCellFactory font-face-combo (build-font-list-cell-factory))
(select-item-in-combo font-face-combo current-face)
font-face-combo))
コンパイラがproxy
の宣言でbuild-font-list-cell
機能で、この上ExceptionInInitializerError
をスローします。 IDE(IntelliJ)は、 'super-proxy`への呼び出しで、updateItem
引数に関する警告を表示し、解決できないことを示します。上記の行の上書きについて不平を言っていないので、なぜ私は理解できません。
これは前に働いていたJavaコードの比較的単純な翻訳のようですが、私は明らかに何かが欠落しています。それともこれが正しいアプローチですか?
EDIT:次のMCVEを追加してください。これはコンパイルされ、表示されているように動作しますが、もちろんフォントのフォント名はフォーマットされません。リスト内のコードのコメントを解除してセルファクトリを作成しようとすると、コンパイラが目にするものが生成されます。
(ns ffcbd.core
(:gen-class
:extends javafx.application.Application)
(:import (javafx.application Application)
(javafx.collections FXCollections)
(javafx.scene.control ComboBox)
(javafx.scene.control.cell TextFieldListCell)
(javafx.scene.text Font)
(javafx.scene.layout BorderPane)
(javafx.scene Scene)
(javafx.stage Stage)
(javafx.util Callback)))
;(defn build-font-list-cell []
; (proxy [TextFieldListCell] []
; (updateItem [family mt]
; (proxy-super updateItem family mt)
; (if mt
; (.setText this nil)
; (do
; (.setFont this (Font/font family))
; (.setText this family))))))
;(defn build-font-list-cell-factory []
; (proxy [Callback] []
; (call [list-view]
; (build-font-list-cell))))
(defn build-font-face-combo []
(let [family-list (FXCollections/observableArrayList (Font/getFamilies))
font-face-combo (ComboBox. family-list)]
; (.setCellFactory font-face-combo (build-font-list-cell-factory))
(.select (.getSelectionModel font-face-combo) 0)
font-face-combo))
(defn -start [this stage]
(let [root (BorderPane.)
scene (Scene. root)]
(.setTop root (build-font-face-combo))
(.add (.getChildren root) (build-font-face-combo))
(.setMinSize root 300 275)
(doto stage
(.setScene scene)
(.setTitle "Font Face ComboBox Demo")
(.show))))
(defn -main [& args]
(Application/launch ffcbd.core args))
Javaのバージョンからのもう1つの違いは、JavaのリストセルがListCell
であるということです。しかし、super.updateItem
に電話する必要があります。私がドキュメントを理解しているので、proxy
は、メソッドがpublic
でない限り、superを呼び出すことはできません。 protected
はListCell
ですが、public
はTextFieldListCell
です。
EDIT#2:ここでは、Javaで動作するコードの例を示します。
package FontFaceDialog;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.layout.BorderPane;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.scene.control.ComboBox;
import javafx.util.Callback;
public class Main extends Application {
private ComboBox<String> buildFontFaceCombo() {
ObservableList<String> lst = FXCollections.observableList(javafx.scene.text.Font.getFamilies());
ComboBox<String> cb = new ComboBox<String>(lst);
cb.getSelectionModel().select(0);
cb.setCellFactory((new Callback<ListView<String>, ListCell<String>>() {
@Override
public ListCell<String> call(ListView<String> listview) {
return new ListCell<String>() {
@Override
protected void updateItem(String family, boolean empty) {
super.updateItem(family, empty);
if (empty) {
setText(null);
} else {
setFont(Font.font(family));
setText(family);
}
}
};
}
}));
return cb;
}
@Override
public void start(Stage primaryStage) throws Exception {
BorderPane root = new BorderPane();
root.setTop(buildFontFaceCombo());
primaryStage.setTitle("Font Face Dialog Example");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
私は ';'の壁は不要であることを指摘したいと思います。フォームの前に置かれた "コメントマクロ"##を使って、フォーム全体をコメントアウトすることができます。 – Carcigenicate
@Carcigenicate:うわー!それは知らなかった。私はちょうどブロックのコードをコメントアウトするためにIDEコマンドを使用しました。とてもかっこいい。 – clartaq
Ya。テストのために関数全体をコメントアウトするのに便利です。 – Carcigenicate