2013-03-27 58 views
17

我想知道是否有可能在每個ListView項目之後添加圖像按鈕。例如:sampleJavaFX - 具有圖像按鈕的ListView項目

其中那些紅色方塊應該有一個按鈕。如果可能,我該如何處理項目按鈕的點擊事件?

編輯:如果有另一個控件可以做到這一點,請讓我知道。我正在測試TableView。

在此先感謝!

回答

27

我最近測試了這個。我的解決辦法:

import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.event.ActionEvent; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.control.ListCell; 
import javafx.scene.control.ListView; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.Pane; 
import javafx.scene.layout.Priority; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 
import javafx.util.Callback; 

public class SO extends Application { 
    static class XCell extends ListCell<String> { 
     HBox hbox = new HBox(); 
     Label label = new Label("(empty)"); 
     Pane pane = new Pane(); 
     Button button = new Button("(>)"); 
     String lastItem; 

     public XCell() { 
      super(); 
      hbox.getChildren().addAll(label, pane, button); 
      HBox.setHgrow(pane, Priority.ALWAYS); 
      button.setOnAction(new EventHandler<ActionEvent>() { 
       @Override 
       public void handle(ActionEvent event) { 
        System.out.println(lastItem + " : " + event); 
       } 
      }); 
     } 

     @Override 
     protected void updateItem(String item, boolean empty) { 
      super.updateItem(item, empty); 
      setText(null); // No text in label of super class 
      if (empty) { 
       lastItem = null; 
       setGraphic(null); 
      } else { 
       lastItem = item; 
       label.setText(item!=null ? item : "<null>"); 
       setGraphic(hbox); 
      } 
     } 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     StackPane pane = new StackPane(); 
     Scene scene = new Scene(pane, 300, 150); 
     primaryStage.setScene(scene); 
     ObservableList<String> list = FXCollections.observableArrayList(
       "Item 1", "Item 2", "Item 3", "Item 4"); 
     ListView<String> lv = new ListView<>(list); 
     lv.setCellFactory(new Callback<ListView<String>, ListCell<String>>() { 
      @Override 
      public ListCell<String> call(ListView<String> param) { 
       return new XCell(); 
      } 
     }); 
     pane.getChildren().add(lv); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

細胞將是這樣的:

Custom List Cell with Button

相關部分是XCell.updateItem方法和setGraphic通話。通過setGraphic()通常應爲標籤設置一個圖標,但它同樣適用於設置複雜的節點 - 在這種情況下,帶有標籤和按鈕的HBox。

您需要確保Button的事件處理程序引用了列表中的正確項目。在下面的第一個鏈接中提到,目前選擇的項目可能已經足夠。因此,在處理按鈕的事件時,請取出列表中當前選定的索引。

你可能想看看這些:

+1

優秀!非常感謝編碼!工作得很好! – Leonardo 2013-04-01 15:17:49

+0

沒有必要將當前項存儲在'lastItem'字段中。你可以直接在按鈕處理程序中調用'getItem()'。 – 2016-12-05 16:32:41

0

以前的解決方案工作得很好,當我的名單並不大,我並沒有增加更多的控制使得節點更復雜。當我添加更多控件時,我發現併發問題,也可能是因爲我繪製的地圖有12000多個對象(線條和多邊形)。問題(我可以看到)是ListView中的一些項目將在內部重複,這意味着cellfactory將被創建兩次和/或未創建。看起來「updateItem」是線程隊列中的最後一個。 所以要解決這個問題,我必須在創建ListView之前創建節點。事情是這樣的:

ObservableList<Node> list = FXCollections.observableArrayList(); 
    for (AisaLayer layer : listLayers) { 
     mapLayers.put(layer.getLayerName(), layer); 
     list.add(new AisaNode(layer)); 
     System.out.println("Ordered:" + layer.getLayerName()); 
    } 
    lv.setItems(list); 
    lv.setCellFactory(new Callback<ListView<Node>, ListCell<Node>>() { 
     @Override 
     public ListCell<Node> call(ListView<Node> param) { 
      return new DefaultListCell<>(); 
     } 
    }); 

我用簡單的DefaultListCell在fxexperience.com

2

您也可以使用自定義HBox中對象的列表建議。下面的例子展示瞭如何使用這種定製的HBox內部類以及將這些對象的嵌套列表過程用於ListView控件。

import java.util.ArrayList; 
import java.util.List; 
import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.collections.ObservableList; 
import javafx.scene.Parent; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.control.ListView; 
import javafx.scene.layout.BorderPane; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.Priority; 
import javafx.stage.Stage; 


public class ListViewDemo extends Application { 

    public static class HBoxCell extends HBox { 
      Label label = new Label(); 
      Button button = new Button(); 

      HBoxCell(String labelText, String buttonText) { 
       super(); 

       label.setText(labelText); 
       label.setMaxWidth(Double.MAX_VALUE); 
       HBox.setHgrow(label, Priority.ALWAYS); 

       button.setText(buttonText); 

       this.getChildren().addAll(label, button); 
      } 
    } 

    public Parent createContent() { 
      BorderPane layout = new BorderPane(); 

      List<HBoxCell> list = new ArrayList<>(); 
      for (int i = 0; i < 12; i++) { 
       list.add(new HBoxCell("Item " + i, "Button " + i)); 
      } 

      ListView<HBoxCell> listView = new ListView<HBoxCell>(); 
      ObservableList<HBoxCell> myObservableList = FXCollections.observableList(list); 
      listView.setItems(myObservableList); 

      layout.setCenter(listView); 

      return layout; 
    } 

    @Override 
    public void start(Stage stage) throws Exception { 
      stage.setScene(new Scene(createContent())); 
      stage.setWidth(300); 
      stage.setHeight(200); 
      stage.show(); 
    } 

    public static void main(String args[]) { 
      launch(args); 
    } 
} 

這個實現的結果是這樣的:

enter image description here

然而,爲了功效管理按鈕事件,你應該增加額外的自定義按鈕對象爲HBoxCustom構造方法考慮,並創建一個適當的方法,這將允許您控制按鈕點擊事件。