2015-10-27 5 views
-1

Я думаю о том, как это сделать в хорошей форме. Я создал программу, которая показывает некоторые пользовательские фигуры в графическом интерфейсе. Теперь, когда я наводил указатель мыши на элемент, я хочу показать некоторую информацию, связанную с этим элементом. В этом примере давайте представим, что каждый элемент является человеком, поэтому я хочу показать некоторые основные сведения об этом человеке (имя, дата рождения, пол ...) при наведении мыши.Подключить пользовательские элементы пользовательского интерфейса с данными

Как подключить данные, которые я имею о человеке к данным элемента, представляет человека?

Насколько я вижу, есть способы сделать это.

  1. Я вставляю данные непосредственно в форму. (Не знаю, как это сделать)
  2. Я использую идентификатор формы для поиска данных.
+2

Вы должны размещать код, что вы пробовали до сих пор. – Tobi

ответ

-1

можно связать пользовательские данные с любым узлом JavaFX, используя setUserData(Object) и getUserData()

Поэтому в вашем случае вы бы просто хранить Person в форме

shape.setUserData(person); 

и внутри мыши над событием извлеките его для отображения данных:

(Person)shape.getUserData(); 
+0

или shape.getProperties(). Put (...) – Marcel

+0

Учитывая, что вы создаете пользовательские элементы пользовательского интерфейса, это похоже на действительно плохое решение. Опираясь на нефинансовую карту без механизма, гарантирующего, что данные существуют или имеют правильный тип, просто кажется невероятно хрупким. Если вы создаете собственные элементы пользовательского интерфейса, почему бы просто не создать свойство для хранения данных? –

+0

@James_D Я думаю, что это несправедливый комментарий. В моих глазах, чтобы иметь возможность связывать объекты пользовательского интерфейса с пользовательскими данными **, является ** полезной функцией, особенно если вы ** не ** получаете собственный класс. И независимо от того, приводит ли это к неустойчивому коду, вопрос о том, как использовать эту функцию. По крайней мере, он показал один путь к ОП, как создать такую ​​ассоциацию. – wero

0

Здесь это другое решение, которое, по моему мнению, гораздо более надежное, чем использование принципиально нетипизированных userData или properties map. Используя любой из этих подходов будет либо загромождать ваш код с проверками на null, и для вещей, которые являются правильным типом, или заставит вас предположить, что код по всему вашему приложению использует элементы интерфейса правильно. Первому из них будет намного сложнее читать (и, следовательно, поддерживать) ваш код. Второе означает, что ваш код уязвим для ошибок, которые трудно отследить (потому что они встречаются в коде, который может быть далеко от кода, где они материализуются).

Либо вы создаете свои элементы пользовательского интерфейса, подклассифицируя их, либо у вас есть способ (или некоторый блок кода) для их создания. В первом случае, вы просто дать подклассу ссылку на данные ему необходимо:

public class PersonNode extends Region { 

    private final Person person ; 

    /** 
    * @parameter person The person this node represents. 
    * @throws NullPointerException if person is null. 
    **/ 
    public PersonNode(Person person) { 
     if (person == null) throw new NullPointerException("Person cannot be null"); 

     // do layout, add nodes to children list, etc... 

     this.person = person ; 

     Popup popup = createPopup(); 
     this.setOnMouseEntered(e -> popup.show(this, e.getScreenX(), e.getScreenY())); 
     this.setOnMouseExited(e -> popup.hide()); 

    } 

    private Popup createPopup() { 
     Label nameLabel = new Label(); 
     nameLabel.textProperty().bind(person.nameProperty()); 
     Label birthdayLabel = new Label(); 
     DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy"); 
     birthdayLabel.textProperty().bind(Bindings.createStringBinding(
      () -> formatter.format(person.getBirthday()), 
      person.birthdayProperty() 
     )); 
     // etc... 
     VBox root = new VBox(10, nameLabel, birthdayLabel); 
     Popup popup = new Popup(); 
     popup.getContent().add(root); 
     return popup ; 
    } 

    public Person getPerson() { 
     return person ; 
    } 
} 

Теперь код приложения прост:

List<Person> personList = ... ; 
Pane somePane = ... ; 

somePane.getChildren().addAll(
    personList.stream().map(PersonNode::new).collect(Collectors.toList())); 

, и это также просто, чтобы добавить другие функциональные возможности пользовательского интерфейса:

for (Person person : personList) { 
    PersonNode node = new PersonNode(person); 
    node.setOnMouseClicked(e -> showPersonEditor(node.getPerson())); 
    somePane.getChildren().add(node); 
} 

Даже если вы не хотите, пользовательский класс UI, вы все еще можете получить большую часть того же эффекта с помощью факторинга создания узлового в метод:

public Node createNodeForPerson(Person person) { 

    Pane personNode = new Pane(); // probably actually use a real layout pane here... 
    // configure personNode with controls or graphics, etc 

    Label nameLabel = new Label(); 
    nameLabel.textProperty().bind(person.nameProperty()); 
    Label birthdayLabel = new Label(); 
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy"); 
    birthdayLabel.textProperty().bind(Bindings.createStringBinding(
     () -> formatter.format(person.getBirthday()), 
     person.birthdayProperty() 
    )); 
    // etc... 
    VBox root = new VBox(10, nameLabel, birthdayLabel); 
    Popup popup = new Popup(); 
    popup.getContent().add(root); 

    personNode.setOnMouseEntered(e -> popup.show(personNode, e.getScreenX(), e.getScreenY())); 
    personNode.setOnMouseExited(e -> popup.hide()); 
    return personNode ; 
} 

(Что здесь происходит, так это то, что всплывающее окно содержит ссылку на Person через привязки, которые определены. В personNode содержится ссылка на всплывающее окно с помощью прослушивателей мыши, поэтому он эффективно сохраняет ссылку на данные Person.)

Теперь, конечно, вы делаете такие вещи, как

for (Person person : personList) { 
    somePane.getChildren().add(createNodeForPerson(person)); 
} 
Смежные вопросы