SwingMetawidget,值未绑定到 JComboBox

SwingMetawidget, value not getting bound to JComboBox

我正在使用 SwingMetawidget。我的数据结构有一个 Person class,其中一个属性是 Title,它也是一个 class,具有从 PersonTitle。 我正在尝试在 MetaWidget 中获得一个 JComboBox ,其值为 Title 绑定。我正在获取通过查找指定的值列表,但在编辑模式下未选择检查 object 中的值。在只读模式下,显示正确的值(我设置了一个从标题到 String 的转换器)。

我的代码如下。我错过了什么?

显示标题的只读模式:

编辑模式,但未选择值"Mr":

编辑模式,显示所有查找值:

主要 Class:

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;
    }
}

人 Class:

@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;
    }


}

标题Class:

@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;
    }
}

感谢您对 Metawidget 的关注!

您的代码存在许多一般性问题,从微不足道到概念上的重要问题。 None 其中本身就是 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 object 不会使用 object 等价(equals 方法)进行匹配。 BeansBinding 和大多数 Java 技术依赖于 object 等价性。所以你需要重写 equalsTitlehashCode 方法。

概念上重要 2

在您的 Converter 中,您试图通过简单地执行以下操作将字符串 ('Mr') 转换为 Title object:

titleObj = new Title(title,null,null,1,1);

这会将 name 设置为 title,但其他字段未初始化 (null) 或初始化为任意值 (1)。特别是 id 未初始化。根据您如何实现 equalshashCode 方法(见上文),这意味着它们永远不会匹配从数据库返回的记录。

结论

我修复了所有这 3 个问题,并且代码按预期工作。但是,您的具体实施会有所不同。特别是您可能需要在 Converter 中进行数据库查找。或者,理想情况下,每个 session 执行一次数据库查找并缓存标题列表 objects.

顺便说一句,Title 上的 OneToMany 可能是 over-normalized(即会导致大量数据库连接)。您最好将 Title 作为字符串存储在每个 Person 中。您仍然可以使用 Title object,以便您可以配置数据库中可能的标题列表。