【发布时间】:2021-12-28 04:35:32
【问题描述】:
我正在尝试通过修改渲染在 JList 中显示 Panel。
我尝试了一个使用 JLabel (https://www.codejava.net/java-se/swing/jlist-custom-renderer-example) 的示例,它运行良好(见图)
所以我尝试将它用于 JPanel(而不是 JLabel),但我遇到了一个有趣的问题,我真的不知道如何解决它。
如您所见,不是只出现一次,而是每个国家和他的相关图像都显示在每一行,我不明白为什么。 (有8行,因为有8个国家)
这是我制作的代码:
CountryRenderer.java
import java.awt.*;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.*;
public class CountryRenderer extends JPanel implements ListCellRenderer<Country> {
@Override
public Component getListCellRendererComponent(JList<? extends Country> list, Country country, int index,
boolean isSelected, boolean cellHasFocus) {
String code = country.getCode();
// to load and resize the image
Image imgSettings = null;
try {
imgSettings = ImageIO.read(getClass().getResource("./images/" + code + "1.png"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
imgSettings = imgSettings.getScaledInstance(25, 25, imgSettings.SCALE_SMOOTH);
// create the button and put the image on it
JButton buttontest = new JButton() ;
buttontest.setIcon(new ImageIcon(imgSettings));
add(buttontest);
// create the text (name of the country)
JTextField txtest = new JTextField();
txtest.setText(country.getName());
add(txtest);
return this;
}
}
如果您需要另外 2 个文件来运行此操作,它们位于我在上面或此处放置的链接上:
Country.java
public class Country {
private String name;
private String code;
public Country(String name, String code) {
this.name = name;
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
@Override
public String toString() {
return name;
}
}
这是您可以运行的文件: JListCustomRendererExample.java
import javax.swing.*;
public class JListCustomRendererExample extends JFrame {
public JListCustomRendererExample() {
Country us = new Country("USA", "1");
Country in = new Country("India", "2");
Country vn = new Country("Vietnam", "3");
Country ca = new Country("Canada", "4");
Country de = new Country("Denmark", "5");
Country fr = new Country("France", "6");
Country gb = new Country("Great Britain", "7");
Country jp = new Country("Japan", "8");
//create the model and add elements
DefaultListModel<Country> listModel = new DefaultListModel<>();
listModel.addElement(us);
listModel.addElement(in);
listModel.addElement(vn);
listModel.addElement(ca);
listModel.addElement(de);
listModel.addElement(fr);
listModel.addElement(gb);
listModel.addElement(jp);
//create the list
JList<Country> countryList = new JList<>(listModel);
add(new JScrollPane(countryList));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setTitle("JList Renderer Example");
this.setSize(200, 200);
this.setLocationRelativeTo(null);
this.setVisible(true);
countryList.setCellRenderer(new CountryRenderer());
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new JListCustomRendererExample();
}
});
}
}
编辑
我尝试了@Gilbert le blanc 的答案,但我仍然遇到问题,我尝试向此标签添加新元素,例如按钮,我希望这些按钮上的文本与名称相同国家行它在。 示例:在 USA 行上,我希望按钮上有“USA”。
所以我在public Component getListCellRendererComponent 中添加了这 4 行:
label.setLayout(null);
JButton test = new JButton(country.getName());
test.setBounds(10,10,50,50);
label.add(test);
我得到了这个:
这不是预期的,这与我在第一个问题中遇到的问题有点相同,你知道为什么吗?有没有解决办法?
【问题讨论】:
-
本教程没有很好地将应用程序模型与 Swing 视图代码和 ListCellRenderer 控制器代码分开。本教程的作者向您展示了他在做什么,但是没有很好地解释为什么他会按照自己的方式做事。他的代码将难以扩展。
-
不要在渲染器中进行 I/O。渲染逻辑应该快速高效,因为在您与 GUI 交互时会多次调用它。图片应该是 Country 类的属性,并在您创建 Country 类时加载。