1. 程式人生 > >JavaFX UI控制元件教程(二十八)之UI控制元件的自定義

JavaFX UI控制元件教程(二十八)之UI控制元件的自定義

翻譯自  Customization of UI Controls

本章介紹了UI控制元件自定義的各個方面,並總結了Oracle提供的一些提示和技巧,以幫助您修改UI控制元件的外觀和行為。

您可以通過應用層疊樣式表(CSS),重新定義預設行為和使用單元工廠來學習如何從UIControlSamples專案中的示例應用程式自定義控制元件。對於更具體的情況,當應用程式的任務需要無法使用javafx.scene.control包的類實現的獨特功能時,請擴充套件Control類以建立自己的控制元件。

應用CSS

您可以通過重新定義JavaFX caspian

樣式表的樣式定義來更改UI控制元件的外觀。使用CSS為JavaFX應用程式設定外觀說明了在JavaFX應用程式中修改樣式並啟用它們的一般概念和方法。

考慮開發人員在JavaFX論壇上經常請求的一些特定任務。

雖然Tooltip該類沒有任何屬性或方法來更改工具提示的預設顏色,但您可以修改CSS類的-fx-background-color屬性,.tooltip例27-1所示。

示例27-1更改工具提示的背景顏色

.tooltip {    
    -fx-background-color: linear-gradient(#e2ecfe, #99bcfd);
}
.page-corner {
    -fx-background-color: linear-gradient(from 0% 0% to 50% 50%,#3278fa,#99bcfd);
}

.page-cornerCSS類定義了提示的右下角的顏色。將示例27-1中的程式碼新增到TooltipSample的樣式表並將樣式表應用於場景時,工具提示將其顏色更改為藍色。請參見圖27-1以評估效果。

圖27-1具有藍色背景顏色的工具提示

請注意,修改工具提示的預設樣式時,新外觀將應用於應用程式中的所有工具提示。

另一個流行的設計任務是更改控制元件的預設標記。例如,類的預設樣式CheckBox定義了所選狀態的傳統複選標記。您可以重新定義標記的形狀及其顏色,如例27-2所示。

示例27-2複選框的替代標記

.check-box .mark {
    -fx-shape:
"M2,0L5,4L8,0L10,0L10,2L6,5L10,8L10,10L8,10L5,6L2,10L0,10L0,8L4,5L0,2L0,0Z";
}
.check-box:selected .mark {
    -fx-background-color: #0181e2;
}

-fx-shape屬性為標記設定新的SVG路徑,-fx-background-color屬性定義其顏色。在CheckBoxSample應用程式中啟用修改後的樣式表時,所選複選框包含X標記而不是複選標記,如圖27-2所示。

圖27-2帶有修改的複選框樣式的ComboBoxSample

許多開發人員詢問如何克服視覺風格TableViewListView控制元件的限制。預設情況下,將顯示這些控制元件中的所有行,無論它們是否為空。使用適當的CSS設定,您可以為所有空行設定特定顏色。例27-3TableView控制元件實現此任務。

示例27-3在表檢視中設定空行的顏色

.table-row-cell:empty {
    -fx-background-color: lightyellow;
}
 
.table-row-cell:empty .table-cell {
    -fx-border-width: 0px;
}

第一種CSS樣式確定所有空行,無論它們是偶數還是奇數,都應該具有淺黃色背景。當table-row-cell為空時,第二個CSS語句將刪除在所有表格單元格右側繪製的垂直邊框。

在TableViewSample應用程式中啟用示例27-3中的CSS樣式時,Address Book表如圖27-3所示。

圖27-3將ColorView新增到空行的TableViewSample

您甚至可以設定null空單元格的背景顏色值。在這種情況下,樣式表將使用表檢視的預設背景顏色。請參見圖27-4以評估效果。

圖27-4將空背景顏色新增到空行的TableViewSample

您可以為UI控制元件設定更多CSS屬性,以更改其形狀,顏色方案和應用的效果。有關可用CSS屬性和類的更多資訊,請參閱“ JavaFX CSS參考指南”

 

改變預設行為

許多開發人員要求使用特定的API來限制文字欄位中的輸入,例如,僅允許數字值。例27-4提供了一個帶有數字文字欄位的簡單應用程式。

示例27-4禁止文字欄位中的字母

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class CustomTextFieldSample extends Application {
    
    final static Label label = new Label();
 
    @Override
    public void start(Stage stage) {
        Group root = new Group();
        Scene scene = new Scene(root, 300, 150);
        stage.setScene(scene);
        stage.setTitle("Text Field Sample");
 
        GridPane grid = new GridPane();
        grid.setPadding(new Insets(10, 10, 10, 10));
        grid.setVgap(5);
        grid.setHgap(5);
 
        scene.setRoot(grid);
        final Label dollar = new Label("$");
        GridPane.setConstraints(dollar, 0, 0);
        grid.getChildren().add(dollar);
        
        final TextField sum = new TextField() {
            @Override
            public void replaceText(int start, int end, String text) {
                if (!text.matches("[a-z, A-Z]")) {
                    super.replaceText(start, end, text);                     
                }
                label.setText("Enter a numeric value");
            }
 
            @Override
            public void replaceSelection(String text) {
                if (!text.matches("[a-z, A-Z]")) {
                    super.replaceSelection(text);
                }
            }
        };
 
        sum.setPromptText("Enter the total");
        sum.setPrefColumnCount(10);
        GridPane.setConstraints(sum, 1, 0);
        grid.getChildren().add(sum);
        
        Button submit = new Button("Submit");
        GridPane.setConstraints(submit, 2, 0);
        grid.getChildren().add(submit);
        
        submit.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                label.setText(null);
            }
        });
        
        GridPane.setConstraints(label, 0, 1);
        GridPane.setColumnSpan(label, 3);
        grid.getChildren().add(label);
        
        scene.setRoot(grid);
        stage.show();
    }
 
    public static void main(String[] args) {
        launch(args);
    }
}

要重新定義類的預設實現TextField,必須覆蓋從類繼承的replaceTextreplaceSelection方法TextInputControl

當用戶嘗試在Sum文字欄位中輸入任何字母時,不會出現符號,並顯示警告訊息。圖27-5說明了這種情況。

圖27-5嘗試輸入字母符號

但是,當用戶嘗試輸入數值時,它們會出現在欄位中,如圖27-6所示。

圖27-6輸入數字值

 

實施細胞工廠

通過使用單元工廠的機制,可以完全定製四個UI控制元件的外觀甚至行為。您可以將電池工廠TableViewListViewTreeView,和ComboBox。單元工廠用於生成單元例項,用於表示這些控制元件的任何單個項。

Cell類擴充套件了Labeled類,它提供了所有必需的屬性和方法,實行最典型的使用情況-顯示和編輯文字。但是,當應用程式的任務需要在列表或表中顯示圖形物件時,您可以使用該graphic屬性並將其放置Node在單元格中(有關自定義單元格的更多資訊,請參閱Cell類API規範)。

例如,示例27-5中的程式碼片段為列表檢視建立了一個單元工廠,並重新定義了updateItem方法中單元格的內容,以便列表顯示不同顏色的矩形。

示例27-5為ListView控制元件實現單元工廠

list.setCellFactory(new Callback<ListView<String>, ListCell<String>>() {
    Override public ListCell<String> call(ListView<String> list) {
        return new ColorRectCell();
    }
});
...
static class ColorRectCell extends ListCell<String> {
    @Override 
    public void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);
        Rectangle rect = new Rectangle(100, 20);
        if (item != null) {
            rect.setFill(Color.web(item));
            setGraphic(rect);
        } else {
            setGraphic(null);
        }
    }
}

圖27-7顯示了此自定義列表在UIControlSamples專案的ListViewSample中的外觀。

圖27-7帶有顏色矩形的列表檢視

本教程廣泛使用單元工廠機制來自定義UI控制元件。表27-1總結了可用於在應用程式上實現單元工廠的編碼模板。

表27-1單元工廠編碼模式

控制 編碼模式

ListView, ComboBox

list.setCellFactory(new Callback<ListView<String>,
ListCell<String>>() {    
            @Override 
            public ListCell<String> call(ListView<String> list) {
               //cell implementation            
            }
});

TableView

column.setCellFactory(new Callback<TableColumn,
    TableCell>() {
        public TableCell call(TableColumn p) {
                    //cell implementation                
                }        
});

TreeView

   tree.setCellFactory(new Callback<TreeView<String>, 
    TreeCell<String>>(){
            @Override
            public TreeCell<String> call(TreeView<String> p) {
                //cell implementation
            }
});

 

您可以使用單元工廠機制自定義這些控制元件,也可以使用預提供的單元編輯器實現來提供視覺化底層的特定資料模型。表27-2列出了JavafX API中可用的相應類。

表27-2列表檢視,樹檢視和表檢視控制元件的單元編輯器類

控制 單元格編輯器類

列表顯示

  • CheckBoxListCell

  • ChoiceBoxListCell

  • ComboBoxListCell

  • TextFieldListCell

樹檢視

  • CheckBoxTreeCell

  • ChoiceBoxTreeCell

  • ComboBoxTreeCell

  • TextFieldTreeCell

表檢視

  • CheckBoxTableCell

  • ChoiceBoxTableCell

  • ComboBoxTableCell

  • ProgressBarTableCell

  • TextFieldTableCell

每個單元格編輯器類在單元格內繪製一個特定節點。例如,CheckBoxListCell該類CheckBox在列表單元格內繪製一個節點。

要評估更多單元工廠和單元編輯器用例,請參閱表檢視樹檢視組合框章節。

 

相關文件和資源