2013-11-14 4 views
7

मैं कस्टम ListView सेल मैं दो नियंत्रण के साथ HBox है है:JavaFX 8 कस्टम ListView कोशिकाओं यह बुराई है

  1. नाम क्षेत्र के साथ लेबल
  2. यह वस्तु

के संदर्भ उदाहरण के लिए से उत्पन्न होगा मैं कक्षा फ़ील्ड की ListView आइटम सरणी सेट करता हूं, यदि फ़ील्ड प्रकार बूलियन मैं चेकबॉक्स बना देता हूं, अगर स्ट्रिंग मैं टेक्स्टफिल्ड और इत्यादि बना रहा हूं

समस्या यह है: मुझे फ़ील्ड ऑब्जेक्ट केवल विधि अद्यतन में मिलता है Item() - और केवल वहां मैं अपने नियंत्रण बना सकता हूं।

जावाएफएक्स 7 में सभी ठीक काम करते हैं, लेकिन जावा 8 पर - मैं अपने नियंत्रण नहीं देखता हूं।

मेरे मामले को हल करने का सही तरीका मौजूद है?

अद्यतन 1

दोहराने समस्या के लिए यहाँ पूर्ण उदाहरण:

package javafx8listviewexample; 

import java.lang.reflect.Field; 
import java.net.URL; 
import java.util.Date; 
import java.util.ResourceBundle; 
import javafx.collections.FXCollections; 
import javafx.event.ActionEvent; 
import javafx.fxml.FXML; 
import javafx.fxml.Initializable; 
import javafx.scene.control.DatePicker; 
import javafx.scene.control.ListCell; 
import javafx.scene.control.ListView; 
import javafx.scene.control.TextField; 
import javafx.scene.control.cell.TextFieldListCell; 
import javafx.util.Callback; 

/** 
* 
* @author dmitrynelepov 
*/ 
public class FXMLDocumentController implements Initializable { 

    static class TestClassForListView { 

     public String fieldString; 
     public Date fieldDate; 
    } 

    static class MyListCell extends ListCell<Field> { 

     /** 
     * As in tutorial 
     * 
     * @param t 
     * @param bln 
     */ 
     @Override 
     protected void updateItem(Field t, boolean bln) { 
      super.updateItem(t, bln); 
      if (t != null) { 
       if (t.getType().equals(String.class)) { 
        System.out.println("Draw string"); 
        setGraphic(new TextField(t.getName())); 
       } else if (t.getType().equals(Date.class)) { 
        System.out.println("Draw Date"); 
        setGraphic(new DatePicker()); 

       } 
      } 
     } 

    } 

    @FXML 
    private ListView<Field> listView; 

    @FXML 
    private void handleButtonAction(ActionEvent event) { 
     this.listView.getItems().clear(); 
     this.listView.setItems(
       FXCollections.observableArrayList(
         TestClassForListView.class.getFields() 
       ) 
     ); 
    } 

    @Override 
    public void initialize(URL url, ResourceBundle rb) { 
     this.listView.setCellFactory(new Callback<ListView<Field>, ListCell<Field>>() { 

      @Override 
      public ListCell<Field> call(ListView<Field> p) { 
       return new MyListCell(); 
      } 
     }); 

    } 

} 

यहां कार्यक्रम JDK के स्क्रीनशॉट 7

enter image description here

के रूप में यू देख सकते हैं मैं TextField ध्यान केंद्रित किया जा सकता है और संपादित किया।

लेकिन मैं

enter image description here

के रूप में यहाँ यू देख सकते हैं TextField केंद्रित है और संपादित किया जा नहीं कर सकते मिला अगर मैं JDK 8 के साथ इस उदाहरण चलाते हैं।

+0

विश्लेषण के लिए पूर्ण, न्यूनतम कोड आपके मुद्दे को दोहराने के लिए महत्वपूर्ण है। यदि आप अपने विशेष कार्यान्वयन के साथ और सहायता चाहते हैं और किसी को यह जांचना और समझाया जाना चाहिए कि यह क्यों काम नहीं करता है, तो आपको एक संपादित प्रश्न में [एसएससीसीई] (http://sscce.org) के रूप में समस्या को दोहराने के लिए कोड रखना होगा)। – jewelsea

+2

हालांकि सवाल बहुत उपयोगी है, क्या आप शीर्षक को अपडेट कर सकते हैं? Javafx8 में कस्टम ListCell ऑब्जेक्ट्स के बारे में आपको इतना बुरा लगता है कि इसे अधिक सटीक रूप से प्रतिबिंबित करना चाहिए। – demongolem

उत्तर

10

ऐसा लगता है कि एक ControlsFX PropertySheet हैं:

propertysheet


ऐसा ही एक कार्यान्वयन, JavaFX 2 TableView : different cell factory depending on the data inside the cell के जवाब में है। भले ही उस प्रश्न का उत्तर TableView, TableView और TableView वर्चुअलाइज्ड नियंत्रण दोनों पर आधारित है, इसलिए कार्यान्वयन अवधारणा कुछ हद तक एक सूची दृश्य का उपयोग करने के समान है जो आपके प्रश्न में उल्लिखित है।

tableproperty


अद्यतन सवाल से नमूना कोड पर आधारित है।

मुझे अभी भी लगता है कि एक कंट्रोलएफएक्स प्रॉपर्टीशीट जो आप पूरा करने की कोशिश कर रहे हैं उसके लिए सबसे उपयुक्त समाधान प्रतीत होता है। वर्चुअलाइज्ड कंट्रोल का उपयोग ऐसे सूची के लिए लिस्ट व्यू जैसे बस चीजों को जितना जटिल होना चाहिए उससे ज्यादा जटिल बनाता है।

ListView आधारित प्रॉपर्टी एडिटर के लिए एक पूर्ण समाधान एक बहुत जटिल चीज है और जो स्टैक ओवरफ्लो उत्तर में उचित रूप से प्रदान किया जा सकता है, उसके दायरे से बाहर है।

आपके प्रश्न में आपके द्वारा प्रदान किए गए नमूना कोड में कुछ समस्याएं हैं।ListView एक वर्चुअलाइज्ड कंट्रोल है, इसलिए आपको सूची दृश्य के अंदर सूचीबद्ध होने के लिए सूची दृश्य के अंदर नए ग्राफिक नोड्स नहीं बनाना चाहिए। क्या होता है कि टेक्स्टफिल्ड फोकस हो जाता है, फिर सूची दृश्य पर अद्यतन कहा जाता है और आप एक नई टेक्स्टफिल्ड बनाते हैं और डिफ़ॉल्ट रूप से नई टेक्स्टफ़िल्ल्ड पर फ़ोकस नहीं होता है।

मुझे लगता है कि ListView में आपके विशेष मामले के लिए कुछ कार्यान्वयन समस्याएं हैं और यह कई बार अपडेट को कॉल कर रहा है। इसके बावजूद, आपको अपना कोड लिखना चाहिए ताकि आप एक सेल पर एकाधिक बार नामक अद्यतन को उचित रूप से संभाल सकें। यदि आप ऐसा करते हैं, तो इससे कोई फर्क नहीं पड़ता कि ListView आपकी विधि को इसकी आवश्यकता के मुकाबले अधिक बार कॉल करता है।

यहां कुछ नमूना कोड है जो आपको और प्रगति करने में मदद कर सकता है। मुझे विश्वास नहीं है कि नमूना कोड आपके मुद्दे का एक संपूर्ण समाधान है, यह निश्चित रूप से जावा ऑब्जेक्ट्स के लिए एक व्यापक प्रॉपर्टी एडिटर के रूप में प्रदान नहीं किया जाता है, लेकिन शायद यह आपको अपने कोड को बेहतर बनाने और कार्यान्वित करने में मदद करने के लिए कुछ प्रेरणा दे सकता है (मानते हुए कि आप निर्णय लेते हैं इस तरह से इस समस्या को हल करने का प्रयास जारी रखें)। यदि आप ListView का उपयोग करना जारी रखते हैं, तो आप ListView के लिए संपादन दिनचर्या देखना चाहते हैं (ओरेकल जावाएफएक्स ट्यूटोरियल में editing table cells के लिए परिभाषित किया गया है)।

import javafx.application.Application; 
import javafx.beans.value.ChangeListener; 
import javafx.collections.FXCollections; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.stage.Stage; 

import java.lang.reflect.Field; 
import java.time.LocalDate; 

/** 
* @author dmitrynelepov 
* Modified by Jewelsea 
*/ 
public class EvilHasSurvived extends Application { 

    static class TestClassForListView { 
     public String fieldString; 
     public LocalDate fieldDate; 

     @Override 
     public String toString() { 
      return "TestClassForListView{" + 
        "fieldString='" + fieldString + '\'' + 
        ", fieldDate=" + fieldDate + 
        '}'; 
     } 
    } 

    static class MyListCell extends ListCell<Field> { 
     private TextField textField; 
     private DatePicker datePicker; 
     private Object editedObject; 
     private ChangeListener<Boolean> editCommitHandler; 

     public MyListCell(Object editedObject) { 
      this.editedObject = editedObject; 
      setContentDisplay(ContentDisplay.RIGHT); 
     } 

     @Override 
     protected void updateItem(Field t, boolean bln) { 
      super.updateItem(t, bln); 

      if (datePicker != null) { 
       datePicker.focusedProperty().removeListener(editCommitHandler); 
      } 
      if (textField != null) { 
       textField.focusedProperty().removeListener(editCommitHandler); 
      } 

      if (t == null) { 
       setText(null); 
       setGraphic(null); 
       return; 
      } 

      if (t.getType().equals(String.class)) { 
       if (textField == null) { 
        textField = new TextField(); 
       } 

       editCommitHandler = (observable, oldValue, newValue) -> { 
        try { 
         t.set(editedObject, textField.getText()); 
         System.out.println(editedObject + " for " + textField + " value " + textField.getText()); 
        } catch (IllegalAccessException e) { 
         e.printStackTrace(); 
        } 
       }; 
       textField.focusedProperty().addListener(editCommitHandler); 

       setText(t.getName()); 
       setGraphic(textField); 
      } else if (t.getType().equals(LocalDate.class)) { 
       if (datePicker == null) { 
        datePicker = new DatePicker(); 
       } 

       editCommitHandler = (observable, oldValue, newValue) -> { 
        try { 
         t.set(editedObject, datePicker.getValue()); 
         System.out.println(editedObject + " for " + datePicker + " value " + datePicker.getValue()); 
        } catch (IllegalAccessException e) { 
         e.printStackTrace(); 
        } 
       }; 
       datePicker.focusedProperty().addListener(editCommitHandler); 

       setText(t.getName()); 
       setGraphic(datePicker); 
      } 
     } 
    } 

    @Override 
    public void start(Stage stage) throws Exception { 
     ListView<Field> listView = new ListView<>(); 
     listView.setItems(
      FXCollections.observableArrayList(
       TestClassForListView.class.getFields() 
      ) 
     ); 
     TestClassForListView testObject = new TestClassForListView(); 
     listView.setCellFactory(p -> new MyListCell(testObject)); 

     stage.setScene(new Scene(listView)); 
     stage.show(); 
    } 

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

यह सही नहीं है कि मुझे क्या चाहिए, और अपडेट करें Item मॉडल अलग-अलग TableView updateItem काम करता है। आप देखते हैं: जब आप टेबल व्यू सेल बनाते हैं तो यह पूरी घटना होती है, लेकिन यदि सूची दृश्य पर उप नोड नियंत्रण के रूप में ऐसा ही होता है - तो यह कॉल दोहराया जाता है। –

+0

कृपया अपने प्रश्न में अपने कोड पोस्ट करें। – jewelsea

+0

अद्यतन प्रश्न: जैसा कि आप देख सकते हैं - अद्यतन में Item - मैं आपके जैसा ही सेट ग्राफिक्स विधि का उपयोग करता हूं। –

संबंधित मुद्दे