You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何单独修改JList某一行颜色?IP检测着色异常问题求助

解决JList中IP地址Ping检测的行着色与实时更新问题

现存问题

  • 所有列表行共用同一个颜色状态,无法单独显示每个IP的可达情况
  • 颜色只有在添加新IP时才更新,无法实时刷新状态

问题根源

  1. 使用全局布尔变量isIpResponding,最后一次Ping的结果会覆盖所有行的显示状态
  2. Ping任务执行完毕后没有通知JList刷新界面
  3. 代码中重复创建JList实例,导致设置的Renderer未生效
  4. 额外维护ipList和model两个数据源,易出现数据不同步

修复方案

  1. 创建IP状态数据类:封装IP地址和对应的可达状态,让每行数据自带状态信息
  2. 移除全局状态变量:为每个IP单独维护可达状态,避免互相影响
  3. 实时触发UI刷新:Ping任务完成后,通过SwingUtilities.invokeLater通知JList更新
  4. 修复JList实例问题:确保整个程序中只使用一个JList实例,Renderer能正确绑定
  5. 自定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 05:15:37