Download ui.py from meccatronis/gpu_monitor: direct link, hf CLI and curl.
- Browser
- Download file 5.47 kB
-
https://huggingface.co/meccatronis/gpu_monitor/resolve/main/ui.py
- Command line
-
hf download hf://meccatronis/gpu_monitor/ui.py
-
curl -L -o ui.py https://huggingface.co/meccatronis/gpu_monitor/resolve/main/ui.py
5.47 kB
| #!/usr/bin/env python3 | |
| """ | |
| Floating Window UI for GPU Monitor | |
| PyQt6-based always-on-top floating window | |
| """ | |
| import sys | |
| from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel, QHBoxLayout, QPushButton | |
| from PyQt6.QtCore import Qt, QPoint, QTimer | |
| from PyQt6.QtGui import QMouseEvent | |
| class FloatingWindow(QWidget): | |
| def __init__(self): | |
| super().__init__() | |
| self.initUI() | |
| self.oldPos = self.pos() | |
| def initUI(self): | |
| # Set window flags for floating behavior | |
| self.setWindowFlags( | |
| Qt.WindowType.WindowStaysOnTopHint | | |
| Qt.WindowType.FramelessWindowHint | | |
| Qt.WindowType.Tool | |
| ) | |
| # Set window properties | |
| self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) | |
| self.setFixedSize(220, 200) | |
| # Create layout | |
| self.layout = QVBoxLayout() | |
| self.layout.setContentsMargins(10, 10, 10, 10) | |
| self.layout.setSpacing(2) | |
| # Set stylesheet | |
| self.setStyleSheet(""" | |
| QWidget { | |
| background-color: rgba(0, 0, 0, 180); | |
| border-radius: 10px; | |
| border: 1px solid #3498db; | |
| } | |
| QLabel { | |
| color: #ecf0f1; | |
| font-family: 'Segoe UI', Arial; | |
| font-size: 12px; | |
| font-weight: bold; | |
| border: none; | |
| } | |
| #title { | |
| color: #3498db; | |
| font-size: 14px; | |
| margin-bottom: 5px; | |
| } | |
| """) | |
| # Create title bar | |
| self.title_layout = QHBoxLayout() | |
| self.title_layout.setContentsMargins(0, 0, 0, 5) | |
| self.lbl_title = QLabel("AMD GPU MONITOR") | |
| self.lbl_title.setObjectName("title") | |
| self.btn_close = QPushButton("×") | |
| self.btn_close.setFixedSize(20, 20) | |
| self.btn_close.setStyleSheet(""" | |
| QPushButton { | |
| background-color: transparent; | |
| color: #e74c3c; | |
| font-size: 18px; | |
| font-weight: bold; | |
| border: none; | |
| margin: 0; | |
| padding: 0; | |
| } | |
| QPushButton:hover { | |
| color: #ff0000; | |
| } | |
| """) | |
| self.btn_close.clicked.connect(self.close) | |
| self.title_layout.addWidget(self.lbl_title) | |
| self.title_layout.addStretch() | |
| self.title_layout.addWidget(self.btn_close) | |
| # Create data labels | |
| self.lbl_load = QLabel("GPU Load: --%") | |
| self.lbl_clocks = QLabel("Clocks: -- / -- MHz") | |
| self.lbl_vram = QLabel("VRAM: -- / -- MB") | |
| self.lbl_temp = QLabel("Temp: --°C") | |
| self.lbl_power = QLabel("Power: --W") | |
| self.lbl_fan = QLabel("Fan: -- RPM (--%)") | |
| # Add widgets to layout | |
| self.layout.addLayout(self.title_layout) | |
| self.layout.addWidget(self.lbl_load) | |
| self.layout.addWidget(self.lbl_clocks) | |
| self.layout.addWidget(self.lbl_vram) | |
| self.layout.addWidget(self.lbl_temp) | |
| self.layout.addWidget(self.lbl_power) | |
| self.layout.addWidget(self.lbl_fan) | |
| self.setLayout(self.layout) | |
| def update_data(self, data): | |
| """Update the UI with new GPU data""" | |
| # Update GPU load | |
| if data['gpu_usage'] is not None: | |
| self.lbl_load.setText(f"GPU Load: {data['gpu_usage']:.1f}%") | |
| else: | |
| self.lbl_load.setText("GPU Load: --%") | |
| # Update clocks | |
| core_clk = data['core_clock'] if data['core_clock'] is not None else "--" | |
| mem_clk = data['mem_clock'] if data['mem_clock'] is not None else "--" | |
| self.lbl_clocks.setText(f"Clocks: {core_clk} / {mem_clk} MHz") | |
| # Update VRAM | |
| if data['vram_used'] is not None and data['vram_total'] is not None: | |
| self.lbl_vram.setText(f"VRAM: {data['vram_used']} / {data['vram_total']} MB") | |
| else: | |
| self.lbl_vram.setText("VRAM: -- / -- MB") | |
| # Update temperature | |
| if data['temperature'] is not None: | |
| self.lbl_temp.setText(f"Temp: {data['temperature']:.1f}°C") | |
| else: | |
| self.lbl_temp.setText("Temp: --°C") | |
| # Update power | |
| if data['power_draw'] is not None: | |
| self.lbl_power.setText(f"Power: {data['power_draw']:.1f}W") | |
| else: | |
| self.lbl_power.setText("Power: --W") | |
| # Update fan | |
| rpm = data['fan_rpm'] if data['fan_rpm'] is not None else "--" | |
| pwm = data['fan_pwm'] if data['fan_pwm'] is not None else "--" | |
| self.lbl_fan.setText(f"Fan: {rpm} RPM ({pwm}%)") | |
| def mousePressEvent(self, event: QMouseEvent): | |
| """Handle mouse press for window dragging""" | |
| if event.button() == Qt.MouseButton.LeftButton: | |
| self.oldPos = event.globalPosition().toPoint() | |
| def mouseMoveEvent(self, event: QMouseEvent): | |
| """Handle mouse move for window dragging""" | |
| if event.buttons() & Qt.MouseButton.LeftButton: | |
| delta = event.globalPosition().toPoint() - self.oldPos | |
| self.move(self.x() + delta.x(), self.y() + delta.y()) | |
| self.oldPos = event.globalPosition().toPoint() | |
| if __name__ == "__main__": | |
| app = QApplication(sys.argv) | |
| window = FloatingWindow() | |
| window.show() | |
| sys.exit(app.exec()) |