【问题标题】:JComboBox + JPAJComboBox + JPA
【发布时间】:2011-03-11 08:18:47
【问题描述】:

考虑到 java 持久性 API 和 JComboBox,我目前陷入 Java 问题。

问题如下:

我有一个 JDialog,我用它来向数据库中添加一些东西。

在视图中:

cbGenre = new JComboBox();
cbPublisher = new JComboBox();

我想要的是在这 2 个组合框中,从 List 或 ArrayList 中加载值。 据我所知,标准是一个只接受字符串数组的组合框。我还发现了一个使用 ArrayList 的示例,我可以使用它。

现在主要的问题是:

我有 2 个表(仅列出重要的列):

games
id pk int
genre int

genre
id pk int
name varchar

它们通过 JPA 以 M:1 关系连接

所以一款游戏只能有一种类型
一种类型可以有一个或多个游戏

我将如何将检索到的流派名称添加到适当的组合框中,当我按下保存按钮时,检索组合框中名称的 id 和该名称的 id?

这可以通过 ArrayList 实现,还是 JCombobox 不允许值对? 我想要这个的原因是,当我将游戏保存到数据库时,我需要选择类型的 id 并将其添加到数据库中,显然,用户不应该看到 id,而是动作,或 RPG 等等不是。

对不起,如果我的问题有点不清楚。如果是,请告诉我,以便我能更好地解释它。

英语不是我的母语,你现在可能已经注意到了:)

感谢阅读,我希望尽快找到解决方案。与此同时,我通过谷歌浏览了更多

【问题讨论】:

    标签: java swing jpa jcombobox


    【解决方案1】:

    组合框接受任何类型的对象。为了显示它们的值,它使用对象的 toString() 方法。所以,你可能有这个代码:

    @Entity
    public class Genre {
        // fields and methods
    
        @Override 
        public String toString() {
            return this.name;
        }
    }
    
    // in your GUI
    List<Genre> genres = findAllGenresSortedByName();
    this.cbGenre = new JComboBox(genres.toArray());
    // ...
    Genre selectedGenre = (Genre) this.cbGenre.getSelectedItem();
    

    如果 Genre 已经有一个您不想更改的 toString 方法,您可以将一个流派包装在一个用于 GUI 的专用类中,并使用 GenreWrappers 的组合框而不是 Genres 的组合框

    public class GenreWrapper {
        private Genre genre;
    
        public GenreWrapper(Genre genre) {
            this.genre = genre;
        }
    
        @Override
        public String toString() {
            return this.genre.getName();
        }
    
        public Genre getGenre() {
            return this.genre;
        }
    }
    

    您绝对应该阅读Swing tutorial,并阅读您正在使用的swing 组件的javadoc。

    【讨论】:

    • 我猜这个问题得到了最好的答案。 +1 提到 Swing 教程(所有 Swing 开发人员的必读)。
    • 谢谢 JB Nizet。一个非常明确的答案。感谢您花时间阅读并提供答案。它提供了我所需要的。从现在开始,我会更好地阅读文档。我确实需要做得更好,而不仅仅是一般搜索。但是,嗯,我已经学习了很多关于 java 的知识 ^^ 我 2 周前从头开始 :) 确实是 +1!
    • 实际上,实现 toString 只是为了显示在组合中(或表或树或任何想要呈现对象的视图)对于原始和包装器来说都是一个坏主意。 Swing'ish 自定义视觉表示(包括字符串表示)的方式是自定义 xxRenderer。 +1 指向教程 :-)
    【解决方案2】:

    你似乎没有理解 Swing 的一个非常重要的事情。据我所知,它是真正 MVC 的最佳实现之一(与我认为 Web MVC2 的折磨相反)。

    因此,每个 Swing 组件都可以使用经典的 MVC 习惯用法来定义。

    例如,对于您的 JComboBox,您有

    • 一个视图:JComboBox 本身
    • 一个模型:ComboBoxModel,在大多数情况下,它是从您提供给它的字符串数组中实例化的
    • 一组控制器:您创建的各种事件处理程序,用于处理视图中的各种事件。

    但是,在另一个层面上,组件扮演着其他角色。如果你检查项目渲染,你可以说你有

    • 一个型号:ComboBoxModel
    • 一个控制器:JComboBox
    • 一个视图:ListCellRenderer 用于显示这些元素

    回到您的问题,假设您将games 组合框模型更改为不保存字符串,而是保存游戏对象。然后,您的组合框将显示类似Game@1548ea8 的字符串,然后您可以使用正确的ListCellRenderer 进行更改。

    在这种情况下,调用JComboBox#getSelectedItem() 将返回给您一个直接可用的游戏。

    如果你对你的流派组合框做同样的事情,我想关联代码会更容易编写。

    【讨论】:

    • 啊!结合上一个答案,我不能要求更多。也非常感谢。 +1。给它游戏对象正是我想要的。
    • @Riduidel:我的回答中没有提到 ListCellRenderer,因为它们在用于更改显示的 String 时会导致问题:显示的字符串是在渲染器中设置的字符串,但组合中的键盘导航box 仍然使用模型元素的 toString() 方法。这就是为什么我更喜欢使用包装对象。我保留颜色、图标等的渲染器。
    • 好吧..我已经使用了包装方法。实际上,我将存储库模式与 MVC 结合使用,或者至少尝试使用它,它似乎主要对我有用。存储库模式,我从我对 ASP.NET MVC 2 的有限知识中偷来的。但是他,我还初级,所以所有这些流行的新东西都很有趣 ^^ 不管是否使用它,我还是会看看列表单元格渲染器,只是为了以后熟悉它。
    • 您确定使用键盘导航吗?我对这些 ListCellRenderers/ComboBoxModel 组合有非常好的经验:使用的 ComboBoxModel 确保项目按照 ListCellRenderer 使用的顺序,这反过来又保证了所有导航方法的正确性。
    • @Riduidel:是的,我确定。查看 JComboBox.DefaultKeySelectionManager 的源代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-05
    • 2013-02-19
    • 2015-02-06
    相关资源
    最近更新 更多