2017-03-24 135 views
2

所以我寫了一個javafx應用程序,我需要能夠從列表視圖中選擇單元格(用於複製粘貼的目的),但我不想讓它可編輯,我的意思是,內容不能改變,除非我想(例如通過按鈕)。如何使ListView可選但不可編輯

所以我有以下代碼:

import javafx.application.Application; 
import javafx.collections.FXCollections; 
import javafx.scene.Scene; 
import javafx.scene.control.ListView; 
import javafx.scene.control.cell.TextFieldListCell; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 
public class Main extends Application { 

    @Override 
    public void start(Stage primaryStage) throws Exception{ 
     List<String> contacts = new ArrayList<>(Arrays.asList("968787522","3424234234","2343234324")); 
     ListView<String> contactsList = new ListView(); 
     contactsList.setItems(FXCollections.observableArrayList(contacts)); 
     //this gives me the ability to edit the row as text field but I want this text field to not be editable 
     contactsList.setCellFactory(TextFieldListCell.forListView()); 
     StackPane pane = new StackPane(); 
     pane.getChildren().add(contactsList); 
     primaryStage.setScene(new Scene(pane, 300, 275)); 
     primaryStage.show(); } 


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

,如果我設置「contactsList」作爲不可編輯,我不能編輯,既沒有選擇。你可以看到(圖像波紋管),我正在編輯單元格,但我希望能夠選擇文本(而不是項目),但我不想刪除字符(文本可選但不可編輯)。 enter image description here

+0

您的代碼工作正常,我。 [編輯]你的問題,以包括一個[MCVE],演示問題。 –

+0

@James_D編輯。希望它更好。 –

回答

1

因此,在突破我的頭,大量研究和API閱讀之後,我想出了一個解決方案。這完全是我想要做的。這裏是演示如果有人需要它;) 所以這個想法是,每當我們想要選擇一行的內容,我們需要選擇行,獲取textField並將編輯設置爲true或false(每次) 。 因此,在我製作的演示中,我放置了一個按鈕,以便您可以將編輯切換爲真或假,以確保它正在工作,以及如何工作。

乾杯。

爲了更好地理解,我評論了一些代碼,如果您對此有任何疑問,請讓我知道。

package sample; 

import com.sun.javafx.scene.control.skin.VirtualFlow; 
import javafx.application.Application; 
import javafx.application.Platform; 
import javafx.collections.FXCollections; 
import javafx.scene.Group; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.scene.control.cell.TextFieldListCell; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.List; 


public class Main extends Application { 
private boolean editable = false; 

public static IndexedCell getCell(final Control control, final int index) { 
    return getVirtualFlow(control).getCell(index); 
} 

public static VirtualFlow<?> getVirtualFlow(Control control) { 
    Group group = new Group(); 
    Scene scene = new Scene(group); 
    Stage stage = new Stage(); 

    if(control.getScene() == null) { 
     group.getChildren().setAll(control); 
     stage.setScene(scene); 
     stage.show(); 
    } 

    VirtualFlow<?>flow = (VirtualFlow<?>) control.lookup("#virtual-flow"); 
    return flow; 
} 

public void setEditable(ListView contactsList){ 
     //this needs to be done since we need to run our code after the text field was rendered 
     //so we need to invoke our code after this happens, if not it will throw a null pointer... 
     Platform.runLater(() -> { 
      //this is one of the most important guys because javafx api says that 
      //TextFieldListCell.forListView() allows editing of the cell content when the cell is double-clicked, 
      // or when {@link ListView#edit(int)} is called. 
      int rowIndex = contactsList.getSelectionModel().getSelectedIndex(); 
      contactsList.edit(rowIndex); 
      ListCell rootCell = (ListCell) getCell(contactsList, rowIndex); 
      TextField textField = (TextField) rootCell.getGraphic(); 
      textField.setEditable(editable); 
     }); 
} 

@Override 
public void start(Stage primaryStage) throws Exception{ 
    List<String> contacts = new ArrayList<>(Arrays.asList("968787522","3424234234","2343234324")); 
    ListView<String> contactsList = new ListView(); 
    contactsList.setItems(FXCollections.observableArrayList(contacts)); 
    contactsList.setEditable(true); 

    //this gives me the ability to edit the row as text field but I want this text field to not be editable 
    contactsList.setCellFactory(TextFieldListCell.forListView()); 
    contactsList.setOnEditStart(e -> { 
     setEditable(contactsList); 
    }); 

    StackPane pane = new StackPane(); 
    Button editBtn = new Button("Toggle edit"); 
    editBtn.setOnAction(event -> { 
     editable = !editable; 
     editBtn.setText("Editing = " + editable); 
     //to cancel any editing that might be occuring 
     contactsList.getSelectionModel().clearSelection(); 
    }); 
    pane.getChildren().addAll(contactsList,editBtn); 
    primaryStage.setScene(new Scene(pane, 300, 275)); 
    primaryStage.show(); 
} 

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

如果我正確理解你,沒有必要將listview設置爲'not editable',因爲默認行爲應該足以滿足你的目的。看看這個代碼,例如:

import javafx.application.Application; 
import javafx.event.EventHandler; 
import javafx.scene.Scene; 
import javafx.scene.control.ListView; 
import javafx.scene.input.MouseEvent; 
import javafx.scene.layout.StackPane; 
import javafx.stage.Stage; 

public class NewFXMain extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     ListView listView = new ListView(); 
     listView.getItems().addAll("one","two","three","four"); 

     listView.setOnMouseClicked(new EventHandler<MouseEvent>() { 
      @Override 
      public void handle(MouseEvent event) { 
       System.out.println(listView.getSelectionModel().getSelectedItem()); 
      } 
     }); 

     StackPane root = new StackPane(); 
     root.getChildren().add(listView); 
     Scene scene = new Scene(root, 300, 250); 

     primaryStage.setTitle("ListView Example"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

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

} 

我什麼也沒有改變對ListView控件的編輯屬性,但我可以選擇每個項目,而不能對其進行編輯(以改變其價值感)。您可以輕鬆地將一個EventHandler添加到ListView中以執行您想要執行的任何操作。您也可以通過操作CellFactory將EventHandler添加到ListView的每個單元格中,如下面的答案所示:How to handle ListView item clicked action?

+0

同樣的問題,我編輯了我的問題給你一個明確的例子。 –

+0

我一開始並不理解你的問題,當我做了,我無法弄清楚:D很好的解決方案,雖然工作得很好:) –

+0

感謝和感謝您的幫助;) –

0

這裏對我來說是什麼在起作用:

TableView<DataBean> table = new TableView<>(); 
    table.setItems(...); // list of some DataBean objects with dataBeanField proprty 
    table.setEditable(true); 

    TableColumn<DataBean, String> column = new TableColumn<>("SomeData"); 
    column.setCellValueFactory(new PropertyValueFactory<DataBean, String>("dataBeanField")); 
    column.setCellFactory(new Callback<TableColumn<DataBean, String>, TableCell<DataBean, String>>() { 
     @Override 
     public TableCell<DataBean, String> call(TableColumn<DataBean, String> param) { 
      return new TextFieldTableCell<>(new DefaultStringConverter() { 
       private String defaultValue = ""; 

       @Override 
       public String fromString(String newValue) { 
        return super.fromString(defaultValue); 
       } 

       @Override 
       public String toString(String value) { 
        return defaultValue = super.toString(value); 
       } 
      }); 
     } 
    });