import os
import sys
import win32gui
import win32con
from PySide6.QtCore import Qt
from PySide6.QtGui import QIcon, QPixmap
from PySide6.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout, QLabel, QSpacerItem, QSizePolicy, QHBoxLayout, QPushButton, QSlider
)
class Shax0(QMainWindow):
"""Shax0 main application with PyWin32 native title bar"""
def __init__(self, parent=None):
super().__init__(parent)
# Define the base path for resources
self.base_path = os.path.join(os.getcwd(), "playback")
# Central widget
central_widget = QWidget()
self.setCentralWidget(central_widget)
# Main vertical layout
self.vBoxLayout = QVBoxLayout(central_widget)
# Create cover art label with updated style
self.coverArtLabel = QLabel(self)
self.coverArtLabel.setText("shax0")
self.coverArtLabel.setStyleSheet("""
background-color: #ECEFF4; /* Slightly lighter gray color for cover art */
border-radius: 15px; /* Rounded corners for cover art */
color: black; /* Black text color */
font-size: 24px; /* Larger font size */
font-family: 'Mononoki'; /* Mononoki font */
font-weight: bold;
""")
self.coverArtLabel.setAlignment(Qt.AlignCenter)
self.coverArtLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # Make cover art expand
# Media control bar with track navigation
self.mediaControlBar = self.createMediaControlBar()
# Add spacers and widgets
self.vBoxLayout.addSpacerItem(QSpacerItem(0, 10, QSizePolicy.Minimum, QSizePolicy.Expanding))
self.vBoxLayout.addWidget(self.coverArtLabel, alignment=Qt.AlignCenter)
self.vBoxLayout.addSpacerItem(QSpacerItem(0, 10, QSizePolicy.Minimum, QSizePolicy.Expanding))
self.vBoxLayout.addLayout(self.mediaControlBar)
# Set up window properties
self.setWindowTitle("shax0")
self.setWindowIcon(QIcon(os.path.join(self.base_path, "gt.png")))
# Set initial window size and center
self.resize(400, 300) # Adjusted window size for compact layout
self.centerWindow()
# Apply native Windows title bar
self.enableNativeTitleBar()
# Apply a translucent effect (for mini player)
self.setWindowOpacity(0.9) # Make the window slightly translucent
self.setStyleSheet("""
QWidget {
background-color: #D8DEE9; /* Slightly gray color for the window background */
color: #2E3440; /* Darker text color for readability */
border-radius: 15px; /* Rounded corners for the entire window */
padding: 10px;
}
QLabel {
color: black; /* Black text for cover art */
}
QPushButton {
background-color: transparent; /* Transparent background for buttons */
color: #4C566A; /* Darker text color for buttons */
border: none; /* Remove button border */
padding: 10px;
border-radius: 5px;
}
QPushButton:hover {
background-color: #A3BE8C; /* Lighter Nord color for hover state */
}
QPushButton:pressed {
background-color: #88C0D0; /* Slightly darker color for pressed state */
}
QSlider {
background-color: #E5E9F0; /* Background of the slider */
height: 6px;
border: none; /* Remove border */
border-radius: 3px; /* Rounded corners */
}
QSlider::groove:horizontal {
background-color: #D8DEE9;
height: 6px;
border-radius: 3px;
}
QSlider::handle:horizontal {
background-color: #4C566A; /* Dark handle */
border-radius: 6px;
width: 14px;
height: 14px;
}
""")
# State for the shuffle button (0: Shuffle, 1: Repeat, 2: Repeat One)
self.current_state = 0
def enableNativeTitleBar(self):
"""Enable the native Windows title bar using PyWin32."""
hwnd = self.winId().__int__()
style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE)
style = style | win32con.WS_CAPTION | win32con.WS_THICKFRAME
win32gui.SetWindowLong(hwnd, win32con.GWL_STYLE, style)
win32gui.SetWindowPos(
hwnd, None, 0, 0, 0, 0,
win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_NOZORDER | win32con.SWP_FRAMECHANGED
)
def createMediaControlBar(self):
"""Create a vertical layout for media controls with icons and track navigation."""
mediaControlBar = QVBoxLayout() # Vertical layout for two rows
# First row: Track Navigation (progress bar, no time numbers)
trackNavigationLayout = QHBoxLayout() # Horizontal layout for progress bar only
self.progressBar = QSlider(Qt.Horizontal)
self.progressBar.setRange(0, 100)
self.progressBar.setValue(0)
trackNavigationLayout.addWidget(self.progressBar)
# Second row: Buttons (play, rewind, stop, forward, shuffle, repeat, wave, terminal)
buttonLayout = QHBoxLayout()
buttons = [
("play.png", "Play"),
("rwd.png", "Rewind"),
("stop.png", "Stop"),
("fwd.png", "Forward"),
("shuffle.png", "Shuffle/Repeat/Repeat One"),
("wave.png", "Wave"),
("terminal.png", "Terminal")
]
for icon_name, tooltip in buttons:
button = self.createIconButton(icon_name, tooltip)
if button: # Only add the button if the icon exists
buttonLayout.addWidget(button)
# Add both rows to the media control bar
mediaControlBar.addLayout(trackNavigationLayout)
mediaControlBar.addLayout(buttonLayout)
return mediaControlBar
def createIconButton(self, icon_name, tooltip):
"""Create a QPushButton with an icon."""
icon_path = os.path.join(self.base_path, icon_name)
if os.path.exists(icon_path):
button = QPushButton()
button.setIcon(QIcon(icon_path))
button.setToolTip(tooltip)
button.setStyleSheet("font-size: 14px; padding: 5px;")
# Connect the button to a slot that cycles the state for shuffle button
if icon_name == "shuffle.png":
button.clicked.connect(self.cycleState)
return button
else:
print(f"Icon not found at: {icon_path}") # Debug log
# Optionally, set a default or error icon
button = QPushButton(tooltip)
button.setStyleSheet("font-size: 14px; color: red; padding: 5px;")
return button
def cycleState(self):
"""Cycle through Shuffle, Repeat, and Repeat One."""
# Cycle state: 0 -> Shuffle, 1 -> Repeat, 2 -> Repeat One
self.current_state = (self.current_state + 1) % 3
if self.current_state == 0: # Shuffle
self.updateButtonState("shuffle.png", "Shuffle")
elif self.current_state == 1: # Repeat
self.updateButtonState("repeat.png", "Repeat")
elif self.current_state == 2: # Repeat One
self.updateButtonState("r1.png", "Repeat One")
def updateButtonState(self, icon_name, tooltip):
"""Update button icon and tooltip."""
button = self.sender() # Get the button that was clicked
icon_path = os.path.join(self.base_path, icon_name)
if os.path.exists(icon_path):
button.setIcon(QIcon(icon_path))
button.setToolTip(tooltip)
def centerWindow(self):
"""Center the window on the screen."""
screen = self.screen().geometry()
size = self.geometry()
self.move(
(screen.width() - size.width()) // 2,
(screen.height() - size.height()) // 2
)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Shax0()
window.show()
sys.exit(app.exec())
использовал pywin32 и pyside6, чтобы создать собственную строку заголовка без qfluentwidgets
пробовал пользовательские панели заголовков, но это не сработало, а пользовательские кнопки закрытия выглядят фальшиво, поэтому я использую pywin32 для стилей Windows.
пожалуйста, помогите, его размер 16x16, а значок в строке заголовка слишком мал. как увеличить его, не нарушая заголовок
У меня возникла проблема с невозможностью сделать значок окна больше 16x16, он слишком мал. [code]import os import sys import win32gui import win32con from PySide6.QtCore import Qt from PySide6.QtGui import QIcon, QPixmap from PySide6.QtWidgets import ( QApplication, QMainWindow, QWidget, QVBoxLayout, QLabel, QSpacerItem, QSizePolicy, QHBoxLayout, QPushButton, QSlider )
class Shax0(QMainWindow): """Shax0 main application with PyWin32 native title bar"""
# Define the base path for resources self.base_path = os.path.join(os.getcwd(), "playback")
# Central widget central_widget = QWidget() self.setCentralWidget(central_widget)
# Main vertical layout self.vBoxLayout = QVBoxLayout(central_widget)
# Create cover art label with updated style self.coverArtLabel = QLabel(self) self.coverArtLabel.setText("shax0") self.coverArtLabel.setStyleSheet(""" background-color: #ECEFF4; /* Slightly lighter gray color for cover art */ border-radius: 15px; /* Rounded corners for cover art */ color: black; /* Black text color */ font-size: 24px; /* Larger font size */ font-family: 'Mononoki'; /* Mononoki font */ font-weight: bold; """) self.coverArtLabel.setAlignment(Qt.AlignCenter) self.coverArtLabel.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # Make cover art expand
# Media control bar with track navigation self.mediaControlBar = self.createMediaControlBar()
# Set up window properties self.setWindowTitle("shax0") self.setWindowIcon(QIcon(os.path.join(self.base_path, "gt.png")))
# Set initial window size and center self.resize(400, 300) # Adjusted window size for compact layout self.centerWindow()
# Apply native Windows title bar self.enableNativeTitleBar()
# Apply a translucent effect (for mini player) self.setWindowOpacity(0.9) # Make the window slightly translucent self.setStyleSheet(""" QWidget { background-color: #D8DEE9; /* Slightly gray color for the window background */ color: #2E3440; /* Darker text color for readability */ border-radius: 15px; /* Rounded corners for the entire window */ padding: 10px; } QLabel { color: black; /* Black text for cover art */ } QPushButton { background-color: transparent; /* Transparent background for buttons */ color: #4C566A; /* Darker text color for buttons */ border: none; /* Remove button border */ padding: 10px; border-radius: 5px; } QPushButton:hover { background-color: #A3BE8C; /* Lighter Nord color for hover state */ } QPushButton:pressed { background-color: #88C0D0; /* Slightly darker color for pressed state */ } QSlider { background-color: #E5E9F0; /* Background of the slider */ height: 6px; border: none; /* Remove border */ border-radius: 3px; /* Rounded corners */ } QSlider::groove:horizontal { background-color: #D8DEE9; height: 6px; border-radius: 3px; } QSlider::handle:horizontal { background-color: #4C566A; /* Dark handle */ border-radius: 6px; width: 14px; height: 14px; } """)
# State for the shuffle button (0: Shuffle, 1: Repeat, 2: Repeat One) self.current_state = 0
def enableNativeTitleBar(self): """Enable the native Windows title bar using PyWin32.""" hwnd = self.winId().__int__() style = win32gui.GetWindowLong(hwnd, win32con.GWL_STYLE) style = style | win32con.WS_CAPTION | win32con.WS_THICKFRAME win32gui.SetWindowLong(hwnd, win32con.GWL_STYLE, style) win32gui.SetWindowPos( hwnd, None, 0, 0, 0, 0, win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_NOZORDER | win32con.SWP_FRAMECHANGED )
def createMediaControlBar(self): """Create a vertical layout for media controls with icons and track navigation.""" mediaControlBar = QVBoxLayout() # Vertical layout for two rows
# First row: Track Navigation (progress bar, no time numbers) trackNavigationLayout = QHBoxLayout() # Horizontal layout for progress bar only self.progressBar = QSlider(Qt.Horizontal) self.progressBar.setRange(0, 100) self.progressBar.setValue(0)
for icon_name, tooltip in buttons: button = self.createIconButton(icon_name, tooltip) if button: # Only add the button if the icon exists buttonLayout.addWidget(button)
# Add both rows to the media control bar mediaControlBar.addLayout(trackNavigationLayout) mediaControlBar.addLayout(buttonLayout)
return mediaControlBar
def createIconButton(self, icon_name, tooltip): """Create a QPushButton with an icon.""" icon_path = os.path.join(self.base_path, icon_name) if os.path.exists(icon_path): button = QPushButton() button.setIcon(QIcon(icon_path)) button.setToolTip(tooltip) button.setStyleSheet("font-size: 14px; padding: 5px;") # Connect the button to a slot that cycles the state for shuffle button if icon_name == "shuffle.png": button.clicked.connect(self.cycleState) return button else: print(f"Icon not found at: {icon_path}") # Debug log # Optionally, set a default or error icon button = QPushButton(tooltip) button.setStyleSheet("font-size: 14px; color: red; padding: 5px;") return button
def cycleState(self): """Cycle through Shuffle, Repeat, and Repeat One.""" # Cycle state: 0 -> Shuffle, 1 -> Repeat, 2 -> Repeat One self.current_state = (self.current_state + 1) % 3
def updateButtonState(self, icon_name, tooltip): """Update button icon and tooltip.""" button = self.sender() # Get the button that was clicked icon_path = os.path.join(self.base_path, icon_name) if os.path.exists(icon_path): button.setIcon(QIcon(icon_path)) button.setToolTip(tooltip)
def centerWindow(self): """Center the window on the screen.""" screen = self.screen().geometry() size = self.geometry() self.move( (screen.width() - size.width()) // 2, (screen.height() - size.height()) // 2 )
[/code] использовал pywin32 и pyside6, чтобы создать собственную строку заголовка без qfluentwidgets пробовал пользовательские панели заголовков, но это не сработало, а пользовательские кнопки закрытия выглядят фальшиво, поэтому я использую pywin32 для стилей Windows. пожалуйста, помогите, его размер 16x16, а значок в строке заголовка слишком мал. как увеличить его, не нарушая заголовок