2016-01-17 9 views
7

के साथ जावाएफएक्स कस्टम सेल फैक्टरी कस्टम की एक सूची के आधार पर कस्टम Cell से कस्टम ListView बनाने का प्रयास कर रहा हूं।कस्टम ऑब्जेक्ट्स

कस्टम वस्तु वर्ग के नाम Message कहा जाता है (पढ़ें, आदि भेजा गया) जो संदेश सामग्री, प्राप्तकर्ता, टाइमस्टैम्प और स्थिति के लिए कुछ क्षेत्रों शामिल हैं।

इस सवाल को देखने के बाद: Customize ListView in JavaFX with FXML मैं सफलतापूर्वक:

  1. कस्टम कोशिकाओं जहां सेल डिजाइन एक FXML फ़ाइल में परिभाषित किया गया है के साथ एक ListView बनाया;
  2. नियंत्रक से जुड़ा हुआ है ताकि प्रत्येक सेल डेटा संग्रह के वर्तमान आइटम से भरा जा सके;

हालांकि, मैं दोनों लिंक करने में विफल: मैं इतना है कि ListView की वर्तमान आइटम सेल नियंत्रक भेज दिया जाता है के लिए एक रास्ता खोजने के लिए प्रतीत नहीं कर सकते हैं।

final ObservableList observableList = FXCollections.observableArrayList(); 
observableList.setAll(myMessages); //assume myMessage is a ArrayList<Message> 
conversation.setItems(observableList); //the listview 
conversation.setCellFactory(new Callback<ListView<Message>, ListCell<Message>>() { 
    @Override 
    public ConversationCell<Message> call(ListView<Message> listView) { 
     return new ConversationCell(); 
    } 
}); 

और अब, ConversationCell वर्ग:

यहाँ सेल कारखाने और मदों की ListView भरने के लिए मेरे कोड है

public final class ConversationCell<Message> extends ListCell<Message> { 

    @Override 
    protected void updateItem(Message item, boolean empty) { 
     super.updateItem(item, empty); 
     ConversationCellController ccc = new ConversationCellController(null); 
     setGraphic(ccc.getView()); 
    } 
} 

मैं ConversationCellController नहीं दिखा सकते हैं लेकिन सभी मैं कह सकता हूँ , यह वह जगह है जहां (इसके कन्स्ट्रक्टर में) मैं FXML फ़ाइल लोड करता हूं जो सेल को डिज़ाइन करता है और फिर मैं दिए गए संदेश आइटम के साथ मानों को भर सकता हूं।

getView() विधि जड़ फलक है कि अब से भरे और डिज़ाइन किया गया कक्ष है देता है।

मैं पहले का कहना है के रूप में, डिजाइन काम है, लेकिन मैं

संरक्षित शून्य updateItem (संदेश आइटम, बूलियन खाली)

क्योंकि विधि में CellFactory साथ ListView आइटम लिंक करने के लिए नहीं कर पा रहे

खालीसच पर सेट है और आइटम वास्तव में अशक्त है।

यह काम करने के लिए मैं क्या कर सकता हूं?

+1

'सभी उदाहरणों पर सही पर सेट किया empty' है? एक सेल को खाली माना जाता है यदि उसके पास कोई वस्तु नहीं है, यानी - यह वास्तविक कोशिकाओं के नीचे की जगह को भरने के लिए है। यदि आपकी सूची दृश्य 10 आइटम दिखाने के लिए काफी बड़ा है लेकिन आपके पास केवल 3 है, तो आपके पास 7 'वार्तालापसेल' ऑब्जेक्ट्स खाली होंगी जो खाली हैं। एक तरफ के रूप में, मैं नहीं देख सकता कि 'वार्तालापसेल नियंत्रक' को आइटम कहां से प्राप्त करना चाहिए। आप अभी भी कुछ आप हो रही है वास्तविक डेटा के साथ कोशिकाओं पर 'खाली = TRUE' यदि आप एक कम से कम उदाहरण इस समस्या का प्रदर्शन के साथ आ सकता है यह मददगार हो सकता है कर रहे हैं। – Itai

+2

मैं 'ListView' कार्यान्वयन शुरू में पर्याप्त कोशिकाओं बनाता प्रदर्शन को भरने के लिए और कॉल' updateItem (शून्य, true) लगता है, 'उन सभी पर है, तो कहता है' updateItem (...) 'गैर खाली वालों पर, साथ उचित डेटा (हालांकि मैं निश्चित नहीं हूं, और अभी स्रोत स्रोत के माध्यम से खोदने का समय नहीं है)। किसी भी दर पर, सभी सेल कार्यान्वयन को खाली सेल केस को संभालना चाहिए। –

+0

"मैं वार्तालापसेल नियंत्रक नहीं दिखा सकता" क्यों नहीं? –

उत्तर

5

updateItem(...) को ओवरराइड करने वाले सभी कस्टम सेल कार्यान्वयन उस विधि से निपटने की आवश्यकता है जहां उस विधि में सेल खाली है। तो तुम

public final class ConversationCell<Message> extends ListCell<Message> { 

    @Override 
    protected void updateItem(Message item, boolean empty) { 
     super.updateItem(item, empty); 
     if (empty) { 
      setGraphic(null); 
     } else { 
      // did you mean to pass null here, or item?? 
      ConversationCellController ccc = new ConversationCellController(null); 
      setGraphic(ccc.getView()); 
     } 
    } 
} 

के साथ इस का एक भोला-भाला ठीक कर सकता है हालांकि, इस प्रदर्शन की दृष्टि से एक अच्छा समाधान नहीं है।आप प्रत्येक बार 0xको एक गैर-खाली सेल के साथ बुलाया जाता है, और यह एक बहुत महंगा महंगी ऑपरेशन (संभावित रूप से फ़ाइल I/O शामिल है, एक जार फ़ाइल से FXML फ़ाइल को अनजिप करना, फ़ाइल को पार्स करना, प्रतिबिंब के बहुत सारे, नए बनाना यूआई तत्व, आदि)। आप एफएक्स एप्लिकेशन थ्रेड से यह पूछना नहीं चाहते कि हर बार उपयोगकर्ता कुछ पिक्सेल द्वारा लिस्ट व्यू को स्क्रॉल करता है। इसके बजाय, अपने सेल नोड कैश चाहिए और updateItem विधि में यह अद्यतन करना चाहिए:

public final class ConversationCell<Message> extends ListCell<Message> { 

    private final ConversationCellController ccc = new ConversationCellController(null); 
    private final Node view = ccc.getView(); 

    @Override 
    protected void updateItem(Message item, boolean empty) { 
     super.updateItem(item, empty); 
     if (empty) { 
      setGraphic(null); 
     } else { 
      ccc.setItem(item); 
      setGraphic(view); 
     } 
    } 
} 

आप ConversationCellController तदनुसार दृश्य (लेबल पर सेट पाठ, आदि आदि) अपडेट कर देता में एक setItem(...) विधि परिभाषित करना चाहिए।

+0

अरे, यह वास्तव में एक बहुत अच्छा मुद्दा है! सीपीयू उपयोग और लेट को कम करने के लिए पहले से जेनरेट किए गए दृश्यों का ट्रैक रखने के लिए व्यूहोल्डर पैटर्न के साथ एंड्रॉइड लिस्ट व्यू एडाप्टर की तरह। मैं आपके विचार की कोशिश करूँगा। क्या आप मुझे यह भी बता सकते हैं कि मैं अपने वर्तमान सेटअप/कोड के साथ घटनाओं को ट्रिगर करने के लिए क्या कर सकता हूं, ताकि एक विशिष्ट सेल अपडेट किया जा सके? मेरे पास एक संदेश भेजने के लिए प्रगति पट्टी है और उदाहरण के लिए, मैं इसकी प्रगति को अपडेट करना चाहता हूं। धन्यवाद ! – Mackovich

+0

अद्यतनों के लिए, जो एक अलग प्रश्न का कुछ है, आप व्यवस्थित कर सकते हैं कि सूची दृश्य आपके 'संदेश' वर्ग में JavaFX गुणों का उपयोग करके और निकालने वाले आइटम सूची बनाकर अपनी कोशिकाओं को अपडेट करता है। Http://stackoverflow.com/questions/23822550/ –

+0

देखें धन्यवाद। में देख लूंगा ! जिस तरह से मैंने आपके समाधान लागू किए हैं और यह ठीक काम करता है। मेरे ऑब्जर्जेबललिस्ट में मेरे पास कई आइटम नहीं थे (बस कुछ ही) लेकिन मुझे स्नैपियर लगता है! वैसे भी, मैंने यह भी देखा कि 'ccc.setItem' को कई बार कहा जाता है इसलिए मुझे कई बार विचारों को सेट करने से बचने के लिए' वार्तालापसेल नियंत्रक 'में एक बूलियन जोड़ना पड़ा। क्या मैं भी ऐसा कर रहा था? अभी के लिए यह काम करता है लेकिन मुझे आश्चर्य है ... धन्यवाद! – Mackovich

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