如何单独修改JList某一行颜色?IP检测着色异常问题求助
解决JList中IP地址Ping检测的行着色与实时更新问题
现存问题
- 所有列表行共用同一个颜色状态,无法单独显示每个IP的可达情况
- 颜色只有在添加新IP时才更新,无法实时刷新状态
问题根源
- 使用全局布尔变量
isIpResponding,最后一次Ping的结果会覆盖所有行的显示状态 - Ping任务执行完毕后没有通知JList刷新界面
- 代码中重复创建JList实例,导致设置的Renderer未生效
- 额外维护
ipList和model两个数据源,易出现数据不同步
修复方案
- 创建IP状态数据类:封装IP地址和对应的可达状态,让每行数据自带状态信息
- 移除全局状态变量:为每个IP单独维护可达状态,避免互相影响
- 实时触发UI刷新:Ping任务完成后,通过
SwingUtilities.invokeLater通知JList更新 - 修复JList实例问题:确保整个程序中只使用一个JList实例,Renderer能正确绑定
- 自定义CellRenderer:根据当前行IP的状态设置对应的背景色
修改后的完整代码
import java.awt.Color; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.IOException; import java.net.InetAddress; import java.util.Timer; import java.util.TimerTask; import javax.swing.DefaultListCellRenderer; import javax.swing.DefaultListModel; import javax.swing.JFrame; import javax.swing.JList; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.JButton; import javax.swing.SwingUtilities; import javax.swing.border.EmptyBorder; public class ListColorRed extends JFrame implements ActionListener { private JTextArea ipInput; private JPanel contentPane; private JButton addBtn; private DefaultListModel<IPStatus> model = new DefaultListModel<>(); private JList<IPStatus> jList; private JScrollPane scrollPane; // 封装IP地址和可达状态的数据类 static class IPStatus { private String ip; private boolean isReachable; public IPStatus(String ip) { this.ip = ip; this.isReachable = false; } public String getIp() { return ip; } public boolean isReachable() { return isReachable; } public void setReachable(boolean reachable) { isReachable = reachable; } @Override public String toString() { return ip; // 列表中显示IP地址 } } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { ListColorRed lcr = new ListColorRed(); lcr.setVisible(true); lcr.startPingTask(); }); } public ListColorRed() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); contentPane = new JPanel(); contentPane.setBackground(Color.WHITE); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(null); addBtn = new JButton("Add"); addBtn.setBounds(250, 75, 89, 23); contentPane.add(addBtn); addBtn.addActionListener(this); JPanel panel = new JPanel(); panel.setBackground(Color.BLUE); panel.setBounds(10, 51, 230, 66); contentPane.add(panel); panel.setLayout(null); ipInput = new JTextArea(); ipInput.setBounds(10, 11, 210, 44); panel.add(ipInput); scrollPane = new JScrollPane(); scrollPane.setBounds(20, 128, 219, 88); contentPane.add(scrollPane); // 只创建一次JList,绑定自定义Renderer jList = new JList<>(model); scrollPane.setViewportView(jList); jList.setCellRenderer(new DefaultListCellRenderer() { @Override public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) { super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); IPStatus status = (IPStatus) value; // 根据当前IP的状态设置颜色 if (status.isReachable()) { setBackground(Color.GREEN); } else { setBackground(Color.RED); } setForeground(Color.WHITE); return this; } }); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == addBtn) { String ip = ipInput.getText().trim(); if (!ip.isEmpty()) { model.addElement(new IPStatus(ip)); ipInput.setText(""); } } } private void pingAllIPs() { for (int i = 0; i < model.size(); i++) { IPStatus status = model.getElementAt(i); try { InetAddress address = InetAddress.getByName(status.getIp()); boolean reachable = address.isReachable(5000); status.setReachable(reachable); System.out.println(status.getIp() + " - " + (reachable ? "Respond" : "No respond")); } catch (IOException ex) { status.setReachable(false); System.out.println(status.getIp() + " - Error: " + ex.getMessage()); } } // Ping完成后在EDT线程中刷新列表UI SwingUtilities.invokeLater(() -> jList.repaint()); } private void startPingTask() { int interval = 5000; // 5秒执行一次Ping任务 Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { pingAllIPs(); } }, 0, interval); } }
关键修改说明
- 新增
IPStatus类,每个对象存储单个IP的地址和可达状态,实现每行数据独立管理 - 移除全局变量
isIpResponding、ipList等,直接通过model管理所有IP状态数据 - 在
pingAllIPs方法中逐个更新每个IP的状态,并通过SwingUtilities.invokeLater触发列表刷新,保证UI操作在EDT线程中执行 - 修复JList重复创建的问题,确保Renderer绑定到正确的列表实例
- CellRenderer中直接获取当前行的
IPStatus对象,根据其状态设置对应颜色
内容的提问来源于stack exchange,提问作者Ljonja2107
相关产品推荐
相关产品推荐

