2016-04-15 13 views
17

Genelde Java, JavaFX ve programlama için biraz yeni ve beynimi kıran bir sorunum var. Özel Nesneleri kullanarak JavaFX'te bir ListView'i nasıl doldurabilirim?

öğreticiler çoğunda ben yapmanın en kolay yolu (daha spesifik olarak, bir ObservableArrayList kullanarak) bir ListView doldurma konusunda bakmis o Strings bir ObservableList onu yapmak şöyle şudur:

ObservableList<String> wordsList = FXCollections.observableArrayList("First word","Second word", "Third word", "Etc."); 
ListView<String> listViewOfStrings = new ListView<>(wordsList); 

Ancak Dizeleri kullanmak istemiyorum. Ben Kelimeler denilen yapılan özel bir nesne kullanmak istiyorum:

ObservableList<Word> wordsList = FXCollections.observableArrayList(); 
wordsList.add(new Word("First Word", "Definition of First Word"); 
wordsList.add(new Word("Second Word", "Definition of Second Word"); 
wordsList.add(new Word("Third Word", "Definition of Third Word"); 
ListView<Word> listViewOfWords = new ListView<>(wordsList); 

Her Kelime nesnesi sadece 2 özelliklere sahiptir: wordString (kelimenin bir dize) ve tanımı (kelimenin tanımının bir başka dize). İkisi için de alıcılarım var.

Bunun nereye gittiğini görebilirsiniz - kod derler ve çalışır, ancak onu uygulamasında görüntülediğimde, ListView'deki her sözcüğün başlıklarını görüntülemek yerine, Word nesnesinin kendisini bir String olarak görüntüler! yerine wordsList doğrudan Kelimeler alarak yerine, wordString erişir, böyle bir yolla

ListView<Word> listViewOfWords = new ListView<>(wordsList); 

:

is burada

Image showing my application and its ListView

Sorum özellikle, bu yeniden yazmak için basit bir yol var GözlemlenebilirArrayList'imin her bir kelimesinde özellik?

Sadece açık olmak gerekirse, bu işlem android için geçerli değildir ve sözcüklerin listesi en sonunda değiştirilecek, kaydedilecek ve yüklenecektir, bu yüzden wordStrings'i tutmak için başka bir dizi oluşturamıyorum. İnternette biraz araştırma yaptım ve 'Hücre Fabrikaları' denen bir şey var gibi görünüyor, ama böyle basit bir problem gibi görünmesi gereksiz yere karmaşık görünüyor ve daha önce de belirttiğim gibi, ben biraz Programlama gelince bir acemi.

Herkes yardımcı olabilir mi? Bu benim ilk kez burada, bu yüzden kodumun yeterince eklenmemesi veya yanlış bir şey yapmam durumunda özür dilerim.

cevap

20

Çözüm Yaklaşımı ben bu sorunu çözmek için bir cell factory kullanılması önerilir

.

listViewOfWords.setCellFactory(param -> new ListCell<Word>() { 
    @Override 
    protected void updateItem(Word item, boolean empty) { 
     super.updateItem(item, empty); 

     if (empty || item == null || item.getWord() == null) { 
      setText(null); 
     } else { 
      setText(item.getWord()); 
     } 
    } 
}); 

Örnek Uygulama

add image

import javafx.application.Application; 
import javafx.collections.*; 
import javafx.scene.Scene; 
import javafx.scene.control.*; 
import javafx.stage.Stage; 

public class CellFactories extends Application {  
    @Override 
    public void start(Stage stage) { 
     ObservableList<Word> wordsList = FXCollections.observableArrayList(); 
     wordsList.add(new Word("First Word", "Definition of First Word")); 
     wordsList.add(new Word("Second Word", "Definition of Second Word")); 
     wordsList.add(new Word("Third Word", "Definition of Third Word")); 
     ListView<Word> listViewOfWords = new ListView<>(wordsList); 
     listViewOfWords.setCellFactory(param -> new ListCell<Word>() { 
      @Override 
      protected void updateItem(Word item, boolean empty) { 
       super.updateItem(item, empty); 

       if (empty || item == null || item.getWord() == null) { 
        setText(null); 
       } else { 
        setText(item.getWord()); 
       } 
      } 
     }); 
     stage.setScene(new Scene(listViewOfWords)); 
     stage.show(); 
    } 

    public static class Word { 
     private final String word; 
     private final String definition; 

     public Word(String word, String definition) { 
      this.word = word; 
      this.definition = definition; 
     } 

     public String getWord() { 
      return word; 
     } 

     public String getDefinition() { 
      return definition; 
     } 
    } 

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

İmplementasyonu amaçlayan kelimenin bir dize temsilini sağlamak için Word sınıfında toString geçersiz olabilir rağmen

Notları Listenizdeki temsil w, ListView'de görüntü nesnesinin görünüm nesnesinin çıkarılması ve ListView'ünüzde gösterimi için bir hücre fabrikası sağlamanızı öneririm. Bu yaklaşımı kullanarak, Word nesnesinin grafiksel görünümünü metinsel toString yöntemi ile bağladığınızdan endişelerinizden ayrılırsınız; Bu yüzden toString farklı çıktılara sahip olabilir (örneğin, bir kelime adı ve hata ayıklama amacıyla bir açıklama ile birlikte Word alanlarında tam bilgi). Ayrıca, bir hücre fabrikası, daha düz bir metin dizesinin ötesinde verilerinizin görsel bir temsilini oluşturmak için çeşitli grafik düğümlerini uygulayabileceğinizden daha esnektir (eğer bunu yapmak isterseniz).

Ayrıca, bir kenara göre, Word'lerinizi immutable objects nesnelerini ayarlayarak çıkarmanızı öneririz. Eğer gerçekten sözcük nesnelerini değiştirmeniz gerekiyorsa, bunun üstesinden gelmenin en iyi yolu, nesne alanları için gözle görülür gözlemlenebilir özelliklere sahip olmaktır. UI'nizin, nesnelerinizin gözlemlenebilir özellikleri değiştikçe güncellenmesini de isterseniz, liste hücrelerinizdeki değişikliklerden haberdar olmak için, ilgili hücrelerdeki değişikliklerin farkında olmanız gerekir (ki bu da biraz daha karmaşıktır). vaka). Kelimeleri içeren listenin zaten gözlenebilir olduğunu ve ListView'in bu listedeki değişikliklerle ilgileneceğini unutmayın, ancak kelime tanımını örneğin görüntülenen bir kelime nesnesinde değiştirdiyseniz, liste görünümünüzün ListView hücre fabrikasında uygun dinleyici mantığı olmayan tanım.

+0

Çok detaylı cevabınız için çok teşekkürler! Şimdilik, toString() yöntemini geçersiz kılmaya çalışacağım, ancak daha iyi anlamak için Hücre Fabrikaları üzerinde daha fazla okuma yapacağım ve ardından öneriye göre kullanmak için uygulamayı değiştireceğim. Sadece her bir kelimenin 'tanımını' bu düzenleme düğmesiyle değiştireceğim ve liste görünümü sadece 'kelime' özelliğini izleyecektir, böylece 'tanım' ile ilgili değişiklikleri izlemeniz gerekmez. –

1

ListView'in Word'de toString() yöntemini çağıran bir nikel bahse girerim. Bunu geçersiz kılmadıysanız, yalnızca ... o kadar yararlı olmayan bilgileri çıkaran varsayılan toString() yöntemini kullanır. Güzel biçimlendirilmiş bir Dizgi çıktısını geçersiz kılın ve gitmek için iyi olmalısınız!

+0

Hmmm, bu mantıklı! Bunu bir şans vereceğim; Şu anda katılmak için bir dersim var, ama daha sonra deneyeceğim ve çalışıp çalışmadığını göreceğim. –

+0

Ancak bu çok iyi bir çözüm değil: “toString()” yönteminin, kullanıcı arayüzünde görüntülenmesini istediğiniz şeyden farklı bir şey döndürmesini isteyebilirsiniz. –

0

ListView'iniz şu anda görüntüleniyor: Word toString(). (Bu sadece bir örnektir) senin sorunun sadece Word sınıfında aşağıdaki yöntemi ekleyin düzeltmek için:

@Override 
public String toString(){ 
    return (this.word + " --- Definition: " + this.definition); 
} 
İlgili konular