无法使用 Renderer 将 Object 实例设置为 JComboBox 的选定项
Unable to set Object instance as selected item of JComboBox with Renderer
我有一个 DAOImplementation class,其方法定义如下。
@Override
public Registration getRegistrationInfoById(int aRegistrationId) {
String SQL = "{CALL getRegistrationInfoById(?)}";
Registration aRegistration = new Registration();
try (Connection con = DBUtil.getConnection(DBType.MYSQL);
CallableStatement cs = con.prepareCall(SQL);) {
cs.setInt(1, aRegistrationId);
try (ResultSet rs = cs.executeQuery();) {
while (rs.next()) {
int gradeLevel = Integer.parseInt(rs.getString(RegistrationTable.GRADELEVEL));
aRegistration.setGradeLevel(gradeLevel);
}
}
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, e.getErrorCode() + "\n" + e.getMessage());
}
return aRegistration;
}//end of method
这个 returns Grade Level 的整数值(1,2,3,4,5,6,7...等等...)我已经验证过,因为我尝试打印aRegistration.getGradeLevel();
返回的输出
现在我的问题是 JComboBox
。我为我的 JComboBox
设置了一个 ListCellRenderer
,它包含所有 GradeLevel
值
public class JComboBoxRenderer_GradeLevel extends JLabel implements ListCellRenderer<Object> {
public JComboBoxRenderer_GradeLevel() {
this.setOpaque(true);
}
@Override
public Component getListCellRendererComponent(JList<? extends Object> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value instanceof GradeLevel) {
this.setText("" + ((GradeLevel) value).getGradelevel());
} else {
this.setText("--");
}
if (isSelected) {
this.setBackground(Color.YELLOW);
this.setForeground(list.getSelectionForeground());
} else {
this.setBackground(list.getBackground());
this.setForeground(list.getForeground());
}
return this;
}
}
并且看起来像预期的那样 JComboBox
。 (GradeLevel
模型被渲染为简单地显示 gradelevel 的 int 值),((GradeLevel) value).getGradelevel());
returns 一个整数值。
我知道即使 JComboBox
的渲染器使用 ((GradeLevel)value).getGradeLevel()
显示 GradeLevel
的整数值,JComboBox
上的实际值仍然被处理作为 GradeLevel
或对象的实例。但不是 String
或 int
.
所以我的问题是当我尝试将选定值设置为 int 值时,它不会更改 JComboBox
的选定值。当我使用 setSelectedItem();
时没有任何反应
这是我尝试为 GUI 做的。
//Grade Level
GradeLevelDaoImpl gldi = new GradeLevelDaoImpl();
List<GradeLevel> gradeLevels = gldi.getAllGradeLevelsInfo();
DefaultComboBoxModel gradeLevelModel = new DefaultComboBoxModel(gradeLevels.toArray());
jcmbGradeLevel.setModel(gradeLevelModel);
jcmbGradeLevel.setRenderer(new JComboBoxRenderer_GradeLevel());
jcmbGradeLevel.setSelectedIndex(-1);
GradeLevel gradeLevel = new GradeLevel();
gradeLevel.setGradelevel(registration.getGradeLevel());
jcmbGradeLevel.setSelectedItem(gradeLevel); //PROBLEM HERE, it doesn't change
JOptionPane
显示这个。
JOptionPane.showMessageDialog(null,"GradeLevel: "+gradeLevel);
JOptionPane.showMessageDialog(null,"GradeLevel: "+gradeLevel.getGradeLevel());
它似乎无法比较我试图将其设置为 (gradeLevel
) 的对象与 JComboBox
具有的对象 (gradeLevels
)。注意单数和复数。
如何操作 类型 以便 setSelectedItem()
与 JComboBox
的类型相匹配?
谢谢。
如果您想通过使用对象的不同实例来实现这一点,但具有相同的属性,那么您需要覆盖 class 的 equals
和 hashcode
方法, 因此组合的属性是唯一的。这是非常重要的,这是一种关系期望,即任何对象 equal
与另一个对象将具有相同的 hashcode
这是一个非常简单的示例,我在 IDE 的自动生成过程中使用了它(因为我很懒),但是,如果您的 Registration
class 具有其他属性与 class 的实例进行比较时应考虑到这一点,您需要对其进行修改以支持它们(同样,任何好的 IDE 都应该能够做到这一点)
public class Registration {
private int gradeLevel;
public Registration(int gradeLevel) {
this.gradeLevel = gradeLevel;
}
public int getGradeLevel() {
return gradeLevel;
}
public void setGradeLevel(int gradeLevel) {
this.gradeLevel = gradeLevel;
}
@Override
public int hashCode() {
int hash = 7;
hash = 73 * hash + this.gradeLevel;
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Registration other = (Registration) obj;
if (this.gradeLevel != other.gradeLevel) {
return false;
}
return true;
}
}
然后使用类似...
Registration a = new Registration(1);
Registration b = new Registration(1);
Registration c = new Registration(2);
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(b.equals(c));
将打印...
true
false
false
这表明代码正在运行。
完成此设置后,您应该能够通过创建 Registration
的实例来更改所选项目,为其添加所需的属性并将其传递给 JComboBox
。
这是一个非常重要且非常普遍的概念,在 Java 中被大量使用,非常值得花时间学习和理解
我有一个 DAOImplementation class,其方法定义如下。
@Override
public Registration getRegistrationInfoById(int aRegistrationId) {
String SQL = "{CALL getRegistrationInfoById(?)}";
Registration aRegistration = new Registration();
try (Connection con = DBUtil.getConnection(DBType.MYSQL);
CallableStatement cs = con.prepareCall(SQL);) {
cs.setInt(1, aRegistrationId);
try (ResultSet rs = cs.executeQuery();) {
while (rs.next()) {
int gradeLevel = Integer.parseInt(rs.getString(RegistrationTable.GRADELEVEL));
aRegistration.setGradeLevel(gradeLevel);
}
}
} catch (SQLException e) {
JOptionPane.showMessageDialog(null, e.getErrorCode() + "\n" + e.getMessage());
}
return aRegistration;
}//end of method
这个 returns Grade Level 的整数值(1,2,3,4,5,6,7...等等...)我已经验证过,因为我尝试打印aRegistration.getGradeLevel();
现在我的问题是 JComboBox
。我为我的 JComboBox
设置了一个 ListCellRenderer
,它包含所有 GradeLevel
值
public class JComboBoxRenderer_GradeLevel extends JLabel implements ListCellRenderer<Object> {
public JComboBoxRenderer_GradeLevel() {
this.setOpaque(true);
}
@Override
public Component getListCellRendererComponent(JList<? extends Object> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
if (value instanceof GradeLevel) {
this.setText("" + ((GradeLevel) value).getGradelevel());
} else {
this.setText("--");
}
if (isSelected) {
this.setBackground(Color.YELLOW);
this.setForeground(list.getSelectionForeground());
} else {
this.setBackground(list.getBackground());
this.setForeground(list.getForeground());
}
return this;
}
}
并且看起来像预期的那样 JComboBox
。 (GradeLevel
模型被渲染为简单地显示 gradelevel 的 int 值),((GradeLevel) value).getGradelevel());
returns 一个整数值。
我知道即使 JComboBox
的渲染器使用 ((GradeLevel)value).getGradeLevel()
显示 GradeLevel
的整数值,JComboBox
上的实际值仍然被处理作为 GradeLevel
或对象的实例。但不是 String
或 int
.
所以我的问题是当我尝试将选定值设置为 int 值时,它不会更改 JComboBox
的选定值。当我使用 setSelectedItem();
这是我尝试为 GUI 做的。
//Grade Level
GradeLevelDaoImpl gldi = new GradeLevelDaoImpl();
List<GradeLevel> gradeLevels = gldi.getAllGradeLevelsInfo();
DefaultComboBoxModel gradeLevelModel = new DefaultComboBoxModel(gradeLevels.toArray());
jcmbGradeLevel.setModel(gradeLevelModel);
jcmbGradeLevel.setRenderer(new JComboBoxRenderer_GradeLevel());
jcmbGradeLevel.setSelectedIndex(-1);
GradeLevel gradeLevel = new GradeLevel();
gradeLevel.setGradelevel(registration.getGradeLevel());
jcmbGradeLevel.setSelectedItem(gradeLevel); //PROBLEM HERE, it doesn't change
JOptionPane
显示这个。
JOptionPane.showMessageDialog(null,"GradeLevel: "+gradeLevel);
JOptionPane.showMessageDialog(null,"GradeLevel: "+gradeLevel.getGradeLevel());
它似乎无法比较我试图将其设置为 (gradeLevel
) 的对象与 JComboBox
具有的对象 (gradeLevels
)。注意单数和复数。
如何操作 类型 以便 setSelectedItem()
与 JComboBox
的类型相匹配?
谢谢。
如果您想通过使用对象的不同实例来实现这一点,但具有相同的属性,那么您需要覆盖 class 的 equals
和 hashcode
方法, 因此组合的属性是唯一的。这是非常重要的,这是一种关系期望,即任何对象 equal
与另一个对象将具有相同的 hashcode
这是一个非常简单的示例,我在 IDE 的自动生成过程中使用了它(因为我很懒),但是,如果您的 Registration
class 具有其他属性与 class 的实例进行比较时应考虑到这一点,您需要对其进行修改以支持它们(同样,任何好的 IDE 都应该能够做到这一点)
public class Registration {
private int gradeLevel;
public Registration(int gradeLevel) {
this.gradeLevel = gradeLevel;
}
public int getGradeLevel() {
return gradeLevel;
}
public void setGradeLevel(int gradeLevel) {
this.gradeLevel = gradeLevel;
}
@Override
public int hashCode() {
int hash = 7;
hash = 73 * hash + this.gradeLevel;
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Registration other = (Registration) obj;
if (this.gradeLevel != other.gradeLevel) {
return false;
}
return true;
}
}
然后使用类似...
Registration a = new Registration(1);
Registration b = new Registration(1);
Registration c = new Registration(2);
System.out.println(a.equals(b));
System.out.println(a.equals(c));
System.out.println(b.equals(c));
将打印...
true
false
false
这表明代码正在运行。
完成此设置后,您应该能够通过创建 Registration
的实例来更改所选项目,为其添加所需的属性并将其传递给 JComboBox
。
这是一个非常重要且非常普遍的概念,在 Java 中被大量使用,非常值得花时间学习和理解