2

JavaFX 2.0 で Clojure を使用して、特定の .xml に任意のノードを持つ TableView を作成していますTableColumn。私はproxyTableCell を作成しました。メソッドでは、使用したい新しい「実際の」ノードに対してUpdateItemさまざまな試みを試みています。たとえば.setGraphicを作成できますが、 への内部呼び出し中に で呼び出しに到達すると、基本的に列がレイアウトしようとしているときに、プログラムがクラッシュしました。ただし、非派生ノード、たとえば独自の単純なボタンなどを配置できるようです。これを行うのに問題はありません。 TableCellCheckBoxTableCell.setGraphicNullPointerExceptionsetPrefWidthTableCellActionEvent

TableCell質問: のインスタンスが別の のグラフィックとして使用されるとクラッシュするのはなぜTableCellですか? TableColumnorTableViewが親か何かになることを期待していると思います。

以下の省略されたコードitemは、値が Java bean/properties である clojure マップである基礎となるデータ項目です。

(defmacro callback 
  "Reifies the callback interface."
  [args & body]
  `(reify javafx.util.Callback
     (~'call [this# ~@args]
       ~@body)))

(defmacro eventhandler
  "Reifies the eventhandler interface."
  [args & body]
  `(reify javafx.event.EventHandler
     (~'handle [this# ~@args]
       ~@body)))

(defn button-cell-factory 
  "Uses a proxy of TableCell because there is no ButtonTableCell in javafx."
  []
  (callback [callback-column]
            (proxy [TableCell] []
              (updateItem [item empty]
                ;; Item is the content of the TableCell, not very interesting since it's just the button and button parameters
                ;; This is the actual TableCell with all the info we are interested in
                (proxy-super updateItem item empty)
                (println "in button-cell proxy updateItem" item empty)
                (if empty nil
                    (let [button (doto (Button. (:name item))
                                   (.setMaxWidth Double/MAX_VALUE)
                                   (.setAlignment Pos/CENTER_LEFT)
                                   (.setOnAction 
                                    (eventhandler [evt]
                                                  (if-let [action (:action item)]
                                                    (let [index (.getIndex this)
                                                          tableview (.getTableView this)
                                                          rowdata (.. tableview (getItems) (get index))]
                                                      (action rowdata)) nil))))
                          imageview (ImageView. (:image item))]
                      (if (not (nil? imageview)) (.setGraphic button imageview))
                      (.setGraphic this button)))))))

(defn generic-cell-factory [spec]
  "Provide arbitrary cell based on data"
  (callback [callback-column]
            (proxy [TableCell] []
              (updateItem [item empty]
                (proxy-super updateItem item empty)
                (or empty 
                    (let [inner-cell (.call (button-cell-factory) callback-column)]
                      (.setGraphic this inner-cell))))))) ;; this crashes when inner-cell is a proxy of TableCell, but not when it's a Button or other non-TableCell node.

(defn make-cell-factory 
  "Generic factory maker.  Dispatches on model, and uses other column specs.
Column in the actual column created.  spec is the full spec map.  The other names
are the values of the map destructured."
  [column {:keys [model] :as spec} ]
  (cond ;; ...
        (= model :generic)    (generic-cell-factory spec)
        ;; ...
        ))

(defn make-tableview 
"colspecs is a map of keys and names."
[colspecs] 
(let [tableview (TableView.)]
  (doseq [{:keys [name key editable minwidth] :as colspec} colspecs]
    (let [col (TableColumn. name)]
      (doto col
        ;; ...
        (.setCellFactory (make-cell-factory col colspec)))
        ;; I can call (button-cell-factory) here just fine, but trying to put a button-cell in TableCell crashes.
      ;; ...
      (.. tableview (getColumns) (add col))))
  tableview))

省略されたエラー:

SEVERE: javafx.scene.control.Control loadSkinClass Failed to load skin 'StringProperty [bean: TableView[id=null, styleClass=table-view], name: skinClassName, value: com.sun.javafx.scene.control.skin.TableViewSkin]' for control TableView[id=null, styleClass=table-view]
java.lang.NullPointerException
    at com.sun.javafx.scene.control.skin.TableCellSkin.computePrefWidth(TableCellSkin.java:102)
    at javafx.scene.Parent.prefWidth(Parent.java:867)
    at javafx.scene.layout.Region.prefWidth(Region.java:1368)
    at javafx.scene.control.Control.computePrefWidth(Control.java:852)
...
4

0 に答える 0