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 объект, который используется для настройки списка возможных заголовков в базе данных.

Другие вопросы по тегам