import sys
import psutil
from PySide6.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QTableWidget, QTableWidgetItem, QHeaderView, QComboBox, QHBoxLayout, QLabel, QLineEdit
from PySide6.QtCore import QTimer, Qt, QThread, Signal
from PySide6.QtGui import QIcon, QPixmap
from collections import defaultdict
import win32gui
import win32ui
from PIL import Image

def make_transparent(image):
    # 将图像转换为带有透明通道的格式
    image = image.convert("RGBA")
    
    # 获取图像的数据
    datas = image.getdata()
    
    # 创建新的图像数据，将黑色背景转换为透明
    new_data = []
    for item in datas:
        if item[0] == 0 and item[1] == 0 and item[2] == 0:  # 黑色
            new_data.append((255, 255, 255, 0))  # 透明
        else:
            new_data.append(item)
    
    # 更新图像数据
    image.putdata(new_data)
    return image

class NetworkMonitorThread(QThread):
    update_signal = Signal(list)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.last_process_net_io = {}
        self.total_process_net_io = defaultdict(lambda: {'bytes_recv': 0, 'bytes_sent': 0})
        self.running = True
        self.process_cache = {}
        self.update_interval = 2  # 更新间隔设为5秒

    def run(self):
        while self.running:
            current_process_net_io = self.get_process_net_io()
            sorted_data = self.process_data(current_process_net_io)
            self.update_signal.emit(sorted_data)
            self.msleep(self.update_interval * 1000)

    def get_process_net_io(self):
        process_net_io = {}
        active_connections = psutil.net_connections()
        active_pids = set(conn.pid for conn in active_connections if conn.pid is not None)
        
        for pid in active_pids:
            try:
                proc = psutil.Process(pid)
                if pid in self.process_cache:
                    name = self.process_cache[pid]
                else:
                    name = proc.name()
                    self.process_cache[pid] = name
                
                io_counters = proc.io_counters()
                process_net_io[pid] = {
                    'name': name,
                    'bytes_recv': io_counters.read_bytes,
                    'bytes_sent': io_counters.write_bytes
                }
            except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                pass
        return process_net_io

    def process_data(self, current_process_net_io):
        sorted_data = []
        for pid, current in current_process_net_io.items():
            last = self.last_process_net_io.get(pid, current)

            download_speed = (current['bytes_recv'] - last['bytes_recv']) / (self.update_interval * 1024)  # KB/s
            upload_speed = (current['bytes_sent'] - last['bytes_sent']) / (self.update_interval * 1024)  # KB/s

            self.total_process_net_io[pid]['bytes_recv'] += current['bytes_recv'] - last['bytes_recv']
            self.total_process_net_io[pid]['bytes_sent'] += current['bytes_sent'] - last['bytes_sent']

            total_downloaded = self.total_process_net_io[pid]['bytes_recv'] / (1024 * 1024)
            total_uploaded = self.total_process_net_io[pid]['bytes_sent'] / (1024 * 1024)

            if download_speed > 0 or upload_speed > 0 or total_downloaded > 0 or total_uploaded > 0:
                sorted_data.append((current['name'], download_speed, upload_speed, total_downloaded, total_uploaded))

        self.last_process_net_io = current_process_net_io

        sort_by = self.parent().sort_combo.currentIndex()
        sorted_data.sort(key=lambda x: (x[1], x[0]) if sort_by == 0 else (x[0], x[1]), reverse=sort_by == 0)
        return sorted_data[:20]  # 只返回前20个进程

    def stop(self):
        self.running = False

class NetworkMonitor(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("Network Traffic Monitor")
        self.setGeometry(100, 100, 800, 600)

        self.table = QTableWidget(self)
        self.table.setColumnCount(6)
        self.table.setHorizontalHeaderLabels(["Icon", "Process", "Download Speed (KB/s)", "Upload Speed (KB/s)", "Downloaded (MB)", "Uploaded (MB)"])
        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

        layout = QVBoxLayout()
        layout.addWidget(self.table)

        self.sort_combo = QComboBox()
        self.sort_combo.addItem("Sort by Download Speed")
        self.sort_combo.addItem("Sort by Process Name")
        self.sort_combo.currentIndexChanged.connect(self.update_network_info)

        self.filter_input = QLineEdit(self)
        self.filter_input.setPlaceholderText("Filter by process name")
        self.filter_input.textChanged.connect(self.update_network_info)

        sort_layout = QHBoxLayout()
        sort_layout.addWidget(QLabel("Sort by:"))
        sort_layout.addWidget(self.sort_combo)
        sort_layout.addWidget(QLabel("Filter:"))
        sort_layout.addWidget(self.filter_input)
        layout.addLayout(sort_layout)

        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

        self.network_thread = NetworkMonitorThread(self)
        self.network_thread.update_signal.connect(self.update_table)
        self.network_thread.start()

        self.icon_cache = {}
        self.default_icon = QIcon("default_icon.png")  # 默认图标路径

    def update_table(self, sorted_data):
        filter_text = self.filter_input.text().lower()
        filtered_data = [data for data in sorted_data if filter_text in data[0].lower() or not filter_text]

        self.table.setRowCount(len(filtered_data))
        for row, data in enumerate(filtered_data):
            process_name = data[0]
            icon_item = QTableWidgetItem()
            icon = self.get_exe_icon(process_name)
            if icon:
                icon_item.setIcon(icon)
            else:
                icon_item.setIcon(self.default_icon)  # 使用默认图标
            self.table.setItem(row, 0, icon_item)

            for col, value in enumerate(data):
                self.table.setItem(row, col + 1, QTableWidgetItem(f"{value:.2f}" if isinstance(value, float) else str(value)))

    def get_exe_icon(self, process_name):
        if process_name in self.icon_cache:
            return self.icon_cache[process_name]

        try:
            # 获取进程的完整路径
            exe_path = None
            for proc in psutil.process_iter(['pid', 'name', 'exe']):
                if proc.info['name'] == process_name:
                    exe_path = proc.info['exe']
                    break

            if not exe_path:
                return None

            # 获取exe文件的图标
            large, small = win32gui.ExtractIconEx(exe_path, 0)
            if not large:
                return None

            # 创建一个设备上下文
            hdc = win32gui.GetDC(0)
            hdc = win32ui.CreateDCFromHandle(hdc)
            hbmp = win32ui.CreateBitmap()
            hbmp.CreateCompatibleBitmap(hdc, 32, 32)

            # 在设备上下文中绘制图标
            hdc = hdc.CreateCompatibleDC()
            hdc.SelectObject(hbmp)
            hdc.DrawIcon((0, 0), large[0])

            # 保存图标到本地文件
            bmpinfo = hbmp.GetInfo()
            bmpstr = hbmp.GetBitmapBits(True)
            img = Image.frombuffer(
                'RGB',
                (bmpinfo['bmWidth'], bmpinfo['bmHeight']),
                bmpstr, 'raw', 'BGRX', 0, 1)

            # 处理图像以去除黑色背景
            img = make_transparent(img)

            # 将图像转换为QPixmap
            img_path = f'temp_icon_{process_name}.png'
            img.save(img_path)
            pixmap = QPixmap(img_path)

            icon = QIcon(pixmap)
            self.icon_cache[process_name] = icon
            return icon
        except Exception as e:
            print(f"Error extracting icon: {e}")
            return None

    def update_network_info(self):
        pass

    def closeEvent(self, event):
        self.network_thread.stop()
        self.network_thread.wait()
        super().closeEvent(event)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = NetworkMonitor()
    window.show()
    sys.exit(app.exec())
。。。。。。。。。。。。
有的程序明明使用网络进行下载或上传，但是我的软件监控显示这个程序下载或上传的速度是0，怎么解决。。。中文回复我