SwingMetawidget, значение не привязано к JComboBox
Я использую SwingMetawidget
, Моя структура данных имеет Person
класс и одно из свойств является Title
который также является классом с отношением "многие к одному" из Person
в Title
, Я пытаюсь получить JComboBox
в MetaWidget со значением границы заголовка. Я получаю список значений, которые я определяю при поиске, но значение в объекте проверки не выбирается в режиме редактирования. В режиме "Только чтение" отображается правильное значение (я установил конвертер из String
).
Мой код ниже. Что мне не хватает?
Режим только для чтения, где отображается заголовок:
Режим редактирования, но значение "Mr" не выбрано:
Режим редактирования, отображаются все значения поиска:
Основной класс:
public class MetaWidgetFrame extends JFrame {
private JPanel contentPane;
private SwingMetawidget metawidget = new SwingMetawidget();
private JPanel contentPanel;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
MetaWidgetFrame frame = new MetaWidgetFrame();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public MetaWidgetFrame() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 473, 281);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
contentPanel = new JPanel();
contentPane.add(contentPanel, BorderLayout.CENTER);
JPanel controlsPanel = new JPanel();
contentPanel.setLayout(new BorderLayout(0, 0));
contentPane.add(controlsPanel, BorderLayout.SOUTH);
JButton btnSave = new JButton("Save");
btnSave.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
savePerson();
}
});
controlsPanel.add(btnSave);
// Set up the objects
Person person = new Person();
person.setUserID(new Integer(1));
person.setFirstName("Raman");
person.setLastName("C V");
Title title = new Title();
title.setTitleId(new Integer(1));
title.setName("Mr");
// Configure Inspectors
CompositeInspectorConfig inspectorConfig = new CompositeInspectorConfig().setInspectors(
new JpaInspector()
, new PropertyTypeInspector()
,new MetawidgetAnnotationInspector()
);
BeansBindingProcessorConfig bbpc = new BeansBindingProcessorConfig();
// Set up the converter from Title to String
bbpc.setConverter(Title.class, String.class, new Converter<Title,String>() {
@Override
public String convertForward(Title title) {
return title.getName();
}
@Override
public Title convertReverse(String title) {
if ( title == null || "".equals( title ) ) {
return null;
}
Title titleObj = new Title(title,null,null,1,1);
return titleObj;
}
});
BeansBindingProcessor bbp = new BeansBindingProcessor(bbpc);
metawidget.setInspector( new CompositeInspector( inspectorConfig ) );
metawidget.addWidgetProcessor(new ReflectionBindingProcessor());
metawidget.addWidgetProcessor(bbp);
GridBagLayoutConfig gbc = new GridBagLayoutConfig();
gbc.setLabelAlignment(SwingConstants.RIGHT);
gbc.setRequiredText("");
gbc.setRequiredAlignment(SwingConstants.RIGHT);
gbc.setLabelSuffix(": ");
GridBagLayout gbl = new GridBagLayout(gbc);
metawidget.setMetawidgetLayout(gbl);
metawidget.setToInspect(person);
contentPanel.add(metawidget, BorderLayout.CENTER);
JXLabel hintLabel = new JXLabel("New label");
contentPanel.add(hintLabel, BorderLayout.NORTH);
JGoodiesValidatorProcessorIMPL jgProcessor = new JGoodiesValidatorProcessorIMPL().setHintLabel(hintLabel);
metawidget.addWidgetProcessor(jgProcessor);
//add a component to show validation messages
JComponent validationResultsComponent = jgProcessor.getValidationResultsComponent();
JPanel errorsPanel = new JPanel(new BorderLayout(0, 0));
contentPanel.add(errorsPanel, BorderLayout.SOUTH);
errorsPanel.add(validationResultsComponent,BorderLayout.CENTER);
pack();
}
public void savePerson() {
JGoodiesValidatorProcessorIMPL validationProcessor = metawidget.getWidgetProcessor(JGoodiesValidatorProcessorIMPL.class);
ValidationResult result = validationProcessor.showValidationErrors().getValidationResults();
if (!result.hasErrors()) {
metawidget.getWidgetProcessor(BeansBindingProcessor.class).save(metawidget );
Person personSaved = metawidget.getToInspect();
System.out.println("" + personSaved);
}
pack();
}
public JPanel getContentPanel() {
return contentPanel;
}
}
Персона Класс:
@Entity
@Table(name = "person", catalog = "mydb")
public class Person {
private Integer userID;
private Title title;
private String firstName;
private String lastName;
public Person() {
}
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "userID", unique = true, nullable = false)
public Integer getUserID() {
return userID;
}
@UiLookup (value={"Mr","Ms","Miss","Mrs"})
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "titleID", nullable = false)
public Title getTitle() {
return this.title;
}
@Column(name = "firstName", nullable = false, length = 10)
public String getFirstName() {
return firstName;
}
@UiSection ("Others")
@Column(name = "lastName", nullable = false, length = 45)
public String getLastName() {
return lastName;
}
public void setUserID(Integer userID) {
this.userID = userID;
}
public void setTitle(Title title) {
this.title = title;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "Person: "
+ "\n userID = " + userID
+ "\n title = " + title
+ "\n titleID = " + title.getTitleId()
+ "\n firstName = " + firstName
+ "\n lastName = " + lastName;
}
}
Название класса:
@Entity
@Table(name = "title", catalog = "emisdb")
public class Title implements java.io.Serializable {
private Integer titleId;
private String name;
private Date createdDate;
private Date modifiedDate;
private int createdBy;
private int modifiedBy;
private Set<User> users = new HashSet<User>(0);
public Title() {
}
@Override
public String toString() {
return name;
}
public Title(String name, Date createdDate, Date modifiedDate, int createdBy, int modifiedBy) {
this.name = name;
this.createdDate = createdDate;
this.modifiedDate = modifiedDate;
this.createdBy = createdBy;
this.modifiedBy = modifiedBy;
}
public Title(String name, Date createdDate, Date modifiedDate, int createdBy, int modifiedBy, Set<User> users) {
this.name = name;
this.createdDate = createdDate;
this.modifiedDate = modifiedDate;
this.createdBy = createdBy;
this.modifiedBy = modifiedBy;
this.users = users;
}
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "titleID", unique = true, nullable = false)
public Integer getTitleId() {
return this.titleId;
}
public void setTitleId(Integer titleId) {
this.titleId = titleId;
}
@Column(name = "name", nullable = false, length = 4)
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
@UiHidden
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "createdDate", nullable = false, length = 19)
public Date getCreatedDate() {
return this.createdDate;
}
public void setCreatedDate(Date createdDate) {
this.createdDate = createdDate;
}
@UiHidden
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "modifiedDate", nullable = false, length = 19)
public Date getModifiedDate() {
return this.modifiedDate;
}
public void setModifiedDate(Date modifiedDate) {
this.modifiedDate = modifiedDate;
}
@UiHidden
@Column(name = "createdBy", nullable = false)
public int getCreatedBy() {
return this.createdBy;
}
public void setCreatedBy(int createdBy) {
this.createdBy = createdBy;
}
@UiHidden
@Column(name = "modifiedBy", nullable = false)
public int getModifiedBy() {
return this.modifiedBy;
}
public void setModifiedBy(int modifiedBy) {
this.modifiedBy = modifiedBy;
}
@UiHidden
@OneToMany(fetch = FetchType.LAZY, mappedBy = "title")
public Set<User> getUsers() {
return this.users;
}
public void setUsers(Set<User> users) {
this.users = users;
}
}
1 ответ
Спасибо за ваш интерес к Metawidget!
Есть ряд общих проблем с вашим кодом, от тривиальных до концептуально важных. По сути, ни одна из них не является проблемой Metawidget. Я постараюсь разбить их
Тривиальные Проблемы
В MetaWidgetFrame
вы создаете person = new Person()
а также title = new Title()
но ты забыл сделать person.setTitle( title )
,
Концептуально важно 1
Как ваш код стоит, если вы пытаетесь:
Title title1 = new Title();
title1.setTitleId(new Integer(1));
title1.setName("Mr");
Title title2 = new Title();
title2.setTitleId(new Integer(1));
title2.setName("Mr");
System.out.println( title1 == title1 ); // will return true
System.out.println( title1.equals( title2 )); // will return false
Вы можете увидеть два Title
объекты с одинаковыми полями не будут совпадать при использовании эквивалентности объектов (equals
метод). BeansBinding и большинство технологий Java полагаются на эквивалентность объектов. Так что вам нужно переопределить как equals
и hashCode
метод Title
,
Концептуально важно 2
В вашем Converter
, вы пытаетесь преобразовать строку ("Мистер") в Title
объект, просто делая:
titleObj = new Title(title,null,null,1,1);
Это устанавливает name
в title
, но остальные поля либо не инициализированы (null
) или инициализируется произвольным значением (1
). В частности, id
не инициализируется. В зависимости от того, как вы реализуете equals
а также hashCode
методы (см. выше), это означает, что они никогда не будут соответствовать записи, которая возвращается из базы данных.
Заключение
Я исправил все 3 из них, и код работает, как ожидалось. Однако ваша конкретная реализация будет отличаться. В частности, вам, вероятно, нужно выполнить поиск в базе данных в вашем Converter
, Или, в идеале, выполнять поиск в базе данных один раз за сеанс и кэшировать список титровальных объектов.
В сторону, имея OneToMany
на Title
может быть чрезмерно нормализован (то есть приведет к большому количеству объединений базы данных). Вам может быть лучше просто хранить Title
как строка в каждом Person
, Вы все еще можете иметь Title
объект, который используется для настройки списка возможных заголовков в базе данных.