基本功能已经实现,可能还有些小逻辑问题需要处理,先发出来大家玩玩吧。
程序就是你的电脑连接了外接的显示器、投影机等扩展显示,那么这个程序直接将你准备好的文件播放到扩展屏上。
全AI编写的,所以可能有点杂乱无章,反正我也看不懂。
import sys
import os
import json
import screeninfo
import win32gui
import win32con, win32com.client
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QListWidget, QPushButton, QFileDialog, QLabel, QSlider,
QComboBox, QGroupBox, QSizePolicy, QSplitter, QFrame)
from PyQt5.QtCore import Qt, QPropertyAnimation, QEasingCurve, QTimer, pyqtSignal, pyqtProperty
from PyQt5.QtGui import QImage, QPixmap, QIcon, QColor, QLinearGradient, QPainter, QFont, QPalette
import vlc
from vlc import State
from PyQt5.QtCore import pyqtProperty
from PyQt5.QtCore import QSize
class StyledGroupBox(QGroupBox):
def __init__(self, title="", parent=None):
super().__init__(title, parent)
self.setStyleSheet("""
QGroupBox {
border: 2px solid #2a82da;
border-radius: 8px;
margin-top: 10px;
padding-top: 15px;
background-color: rgba(20, 30, 50, 180);
color: #ffffff;
font-weight: bold;
}
QGroupBox::title {
subcontrol-origin: margin;
left: 10px;
padding: 0 5px;
}
""")
class StyledButton(QPushButton):
def __init__(self, text="", parent=None):
super().__init__(text, parent)
self.setStyleSheet("""
QPushButton {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #3a7bd5, stop:1 #00d2ff);
border: 1px solid #2a82da;
border-radius: 5px;
color: white;
padding: 5px;
font-weight: bold;
min-width: 80px;
}
QPushButton:hover {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #4a8be5, stop:1 #10e2ff);
border: 1px solid #3a92ea;
}
QPushButton:pressed {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1,
stop:0 #2a6bc5, stop:1 #00c2ef);
padding-top: 6px;
padding-bottom: 4px;
}
""")
class StyledListWidget(QListWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setStyleSheet("""
QListWidget {
background-color: rgba(30, 40, 60, 200);
border: 1px solid #2a82da;
border-radius: 5px;
color: #ffffff;
font-size: 12px;
padding: 5px;
}
QListWidget::item {
border-bottom: 1px solid rgba(42, 130, 218, 50);
padding: 5px;
}
QListWidget::item:selected {
background-color: rgba(42, 130, 218, 150);
color: white;
}
QScrollBar:vertical {
border: none;
background: rgba(30, 40, 60, 200);
width: 10px;
margin: 0px;
}
QScrollBar::handle:vertical {
background: #2a82da;
min-height: 20px;
border-radius: 4px;
}
QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
height: 0px;
}
""")
class StyledSlider(QSlider):
def __init__(self, orientation=Qt.Horizontal, parent=None):
super().__init__(orientation, parent)
if orientation == Qt.Horizontal:
self.setStyleSheet("""
QSlider::groove:horizontal {
height: 6px;
background: rgba(30, 40, 60, 200);
border-radius: 3px;
}
QSlider::sub-page:horizontal {
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop:0 #3a7bd5, stop:1 #00d2ff);
border-radius: 3px;
}
QSlider::add-page:horizontal {
background: rgba(42, 130, 218, 50);
border-radius: 3px;
}
QSlider::handle:horizontal {
width: 14px;
margin: -4px 0;
background: qradialgradient(cx:0.5, cy:0.5, radius:0.5,
fx:0.5, fy:0.5,
stop:0 #ffffff, stop:1 #2a82da);
border-radius: 7px;
}
""")
else:
self.setStyleSheet("""
QSlider::groove:vertical {
width: 6px;
background: rgba(30, 40, 60, 200);
border-radius: 3px;
}
QSlider::sub-page:vertical {
background: qlineargradient(x1:0, y1:1, x2:0, y2:0,
stop:0 #3a7bd5, stop:1 #00d2ff);
border-radius: 3px;
}
QSlider::add-page:vertical {
background: rgba(42, 130, 218, 50);
border-radius: 3px;
}
QSlider::handle:vertical {
height: 14px;
margin: 0 -4px;
background: qradialgradient(cx:0.5, cy:0.5, radius:0.5,
fx:0.5, fy:0.5,
stop:0 #ffffff, stop:1 #2a82da);
border-radius: 7px;
}
""")
class StyledComboBox(QComboBox):
def __init__(self, parent=None):
super().__init__(parent)
self.setStyleSheet("""
QComboBox {
background-color: rgba(30, 40, 60, 200);
border: 1px solid #2a82da;
border-radius: 5px;
color: white;
padding: 5px;
padding-left: 10px;
min-width: 100px;
}
QComboBox:hover {
border: 1px solid #3a92ea;
}
QComboBox::drop-down {
subcontrol-origin: padding;
subcontrol-position: top right;
width: 20px;
border-left: 1px solid #2a82da;
border-top-right-radius: 5px;
border-bottom-right-radius: 5px;
}
QComboBox::down-arrow {
image: url(none);
width: 10px;
height: 10px;
}
QComboBox QAbstractItemView {
background-color: rgba(30, 40, 60, 200);
border: 1px solid #2a82da;
selection-background-color: rgba(42, 130, 218, 150);
color: white;
}
""")
class ExtendedScreenPlayer(QMainWindow):
def __init__(self):
win32com.client.CoInitialize() # 显式初始化COM组件
def get_volume(self):
return self.main_player.audio_get_volume()
def set_volume(self, volume):
"""设置音量"""
self.current_volume = volume
self.main_player.audio_set_volume(volume) # 修正为main_player
volume = pyqtProperty(int, get_volume, set_volume)
def __init__(self):
super().__init__()
self.playlist =
self.current_index = -1
self.instance = vlc.Instance("--aout=directsound")
self.main_player = self.instance.media_player_new("--aout=directsound") # 主播放器
self.preview_player = self.instance.media_player_new("--aout=directsound") # 预览播放器
self.mode = "扩展模式" # 默认模式
self.screen_modes =
self.play_mode = True # 新增播放模式状态 True=连续播放
self._volume = 100 # 新增私有属性
self.setup_ui_style()
self.init_ui()
self.init_screens()
self.show() # 确保窗口显示
self.show_home_screen() # 调用显示首页画面的方法
self.setAcceptDrops(True)
# 初始化动画相关
self.fade_timer = QTimer(self)
self.fade_timer.timeout.connect(self.fade_process)
self.fade_duration = 8000
self.fade_steps = 30
self.fade_step_interval = self.fade_duration // self.fade_steps
self.fade_animation = None
self.fading_out = False
self.fading_in = False
self.current_volume = 100
# 媒体状态定时器
self.media_timer = QTimer(self)
self.media_timer.timeout.connect(self.update_media_status)
self.media_timer.start(200)
def setup_ui_style(self):
"""设置全局UI样式"""
self.setStyleSheet("""
QMainWindow {
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:1,
stop:0 #0f2027, stop:1 #2c5364);
color: #ffffff;
}
QLabel {
color: #ffffff;
font-size: 12px;
}
QLabel#status_label {
font-size: 14px;
font-weight: bold;
padding: 5px;
background-color: rgba(20, 30, 50, 180);
border-radius: 5px;
border: 1px solid #2a82da;
}
""")
# 设置全局字体
font = QFont()
font.setFamily("Arial")
font.setPointSize(10)
QApplication.setFont(font)
def init_ui(self):
self.setWindowTitle('大屏播控系统')
self.setWindowIcon(QIcon('icon.png')) if os.path.exists('icon.png') else None
self.setGeometry(100, 100, 1200, 800)
# 主布局
main_widget = QWidget()
self.setCentralWidget(main_widget)
main_layout = QHBoxLayout()
main_widget.setLayout(main_layout)
# 左侧控制面板
control_panel = StyledGroupBox("控制面板")
control_layout = QVBoxLayout()
control_panel.setLayout(control_layout)
control_panel.setFixedWidth(450)
# 播放列表
self.playlist_widget = StyledListWidget()
self.playlist_widget.itemDoubleClicked.connect(self.play_selected_item)
control_layout.addWidget(QLabel("播放列表:"))
control_layout.addWidget(self.playlist_widget)
# 播放控制按钮
btn_layout = QHBoxLayout()
controls = [
('🏠', self.show_home_screen, '返回首页画面'),
('⏮', self.prev_item, '播放上一项'),
('⏯', self.toggle_play, '播放/暂停'),
('⏹', self.stop, '停止播放'),
('⏭', self.next_item, '播放下一项')
]
for text, callback, tip in controls:
btn = StyledButton(text)
btn.clicked.connect(callback)
btn.setFixedSize(70, 50)
btn.setToolTip(tip)
btn.setStyleSheet("""
QPushButton {
font-size: 20px;
min-width: 30px;
}
""")
btn_layout.addWidget(btn)
control_layout.addLayout(btn_layout)
# 进度条
self.position_slider = StyledSlider(Qt.Horizontal)
self.position_slider.setRange(0, 1000)
self.position_slider.sliderMoved.connect(self.set_position)
control_layout.addWidget(self.position_slider)
# 音量控制
volume_layout = QHBoxLayout()
volume_layout.addWidget(QLabel("音量:"))
self.volume_slider = StyledSlider(Qt.Horizontal)
self.volume_slider.setRange(0, 100)
self.volume_slider.setValue(100)
self.volume_slider.valueChanged.connect(self.set_volume)
volume_layout.addWidget(self.volume_slider)
control_layout.addLayout(volume_layout)
# 文件操作按钮
file_btn_layout = QHBoxLayout()
file_controls = [
('添加文件', self.add_files),
('删除选中', self.remove_selected),
('清空列表', self.clear_playlist)
]
for text, callback in file_controls:
btn = StyledButton(text)
btn.clicked.connect(callback)
file_btn_layout.addWidget(btn)
control_layout.addLayout(file_btn_layout)
# 播放模式选择
self.mode_combo = StyledComboBox()
self.mode_combo.addItems(self.screen_modes)
self.mode_combo.currentTextChanged.connect(self.change_mode)
control_layout.addWidget(QLabel("播放模式:"))
control_layout.addWidget(self.mode_combo)
# 新增播放模式切换按钮
self.play_mode_btn = StyledButton('连续播放')
self.play_mode_btn.clicked.connect(self.toggle_play_mode)
control_layout.addWidget(self.play_mode_btn)
# 列表管理按钮
list_btn_layout = QHBoxLayout()
list_controls = [
('保存列表', self.save_playlist),
('加载列表', self.load_playlist)
]
for text, callback in list_controls:
btn = StyledButton(text)
btn.clicked.connect(callback)
list_btn_layout.addWidget(btn)
control_layout.addLayout(list_btn_layout)
# 右侧预览区域
preview_panel = StyledGroupBox("预览")
preview_layout = QVBoxLayout()
preview_panel.setLayout(preview_layout)
# 视频预览窗口
self.preview_window = QLabel()
self.preview_window.setAlignment(Qt.AlignCenter)
self.preview_window.setStyleSheet("""
QLabel {
background-color: black;
border: 2px solid #2a82da;
border-radius: 5px;
}
""")
self.preview_window.setSizePolicy(QSizePolicy.Ignored, QSizePolicy.Ignored)
preview_layout.addWidget(self.preview_window)
# 状态栏
self.status_bar = QLabel('大屏准备就绪')
self.status_bar.setObjectName("status_label")
preview_layout.addWidget(self.status_bar)
# 主布局添加组件
main_layout.addWidget(control_panel)
main_layout.addWidget(preview_panel)
def play_selected_item(self, item):
"""处理双击播放列表项事件"""
row = self.playlist_widget.row(item)
self.play_item(row)
def init_screens(self):
"""初始化屏幕配置"""
try:
self.screens = screeninfo.get_monitors()
if len(self.screens) > 1:
self.ext_screen = self.screens
self._create_video_window()
self._hide_taskbar() # 这里调用了隐藏任务栏的方法
else:
self.status_bar.setText('警告:未检测到扩展屏幕,将使用主屏幕播放!')
self._create_fallback_window()
except Exception as e:
self.status_bar.setText(f'屏幕检测失败: {str(e)}')
self._create_fallback_window()
def _create_video_window(self):
"""创建扩展屏播放窗口"""
self.video_window = QWidget()
self.video_window.setWindowTitle('扩展屏幕播放器')
self.video_window.setGeometry(
self.ext_screen.x, self.ext_screen.y,
self.ext_screen.width, self.ext_screen.height
)
self.video_window.setWindowFlags(Qt.FramelessWindowHint | Qt.Tool)
self.video_window.setStyleSheet("background-color: black;")
self.video_window.showFullScreen()
def _create_fallback_window(self):
"""创建集成到主界面右侧的监看窗口"""
self.video_window = self.preview_window # 使用预览窗口作为回退
self.preview_player.set_hwnd(0) # 禁用预览播放器输出
def change_mode(self, mode):
"""切换播放模式"""
self.mode = mode
if mode == "扩展模式" and hasattr(self, 'ext_screen'):
self._create_video_window()
else:
if hasattr(self, 'video_window') and self.video_window != self.preview_window:
self.video_window.close()
self.video_window = self.preview_window
def toggle_play_mode(self):
"""切换播放模式"""
self.play_mode = not self.play_mode
self.play_mode_btn.setText('连续播放' if self.play_mode else '单个播放')
def update_media_status(self):
"""更新媒体状态"""
if self.main_player.is_playing(): # 替换self.player为main_player
# 更新进度条
position = self.main_player.get_position() * 1000 # 替换为main_player
self.position_slider.setValue(int(position))
# 更新预览画面
if self.mode != "扩展模式" or not hasattr(self, 'ext_screen'):
self.update_preview()
else:
# 检测播放完成
if self.main_player.get_state() == vlc.State.Ended and self.playlist: # 替换为main_player
if self.play_mode: # 连续播放模式
self.next_item()
else: # 单个播放模式
self.stop()
self.show_home_screen()
def toggle_play(self):
if self.main_player.is_playing(): # 替换为main_player
self.main_player.pause() # 替换为main_player
self.status_bar.setText('已暂停')
else:
if self.playlist:
selected = self.playlist_widget.currentRow()
self.play_item(selected if selected != -1 else 0)
def set_volume(self, volume):
"""设置音量"""
self.current_volume = volume
self.main_player.audio_set_volume(volume) # 修正为main_player
def add_files(self):
files, _ = QFileDialog.getOpenFileNames(
self, '选择媒体文件', '',
'媒体文件 (*.mp4 *.avi *.mov *.mkv *.mp3 *.wav *.jpg *.jpeg *.png)')
if files:
self.playlist.extend(files)
self.playlist_widget.addItems()
if self.current_index == -1:
self.current_index = 0
def play_item(self, index):
if 0 <= index < len(self.playlist):
self.current_index = index
file_path = self.playlist
is_image = file_path.lower().endswith(('.jpg', '.jpeg', '.png'))
if not self.play_mode and is_image:
self._setup_single_image_playback()
# 清除之前显示的图片
if hasattr(self, 'video_window') and self.video_window != self.preview_window:
for child in self.video_window.findChildren(QLabel):
child.deleteLater()
try:
pixmap = QPixmap(file_path)
if pixmap.isNull():
raise ValueError("图片加载失败")
# 在主预览窗口显示
scaled_pixmap = pixmap.scaled(
QSize(800, 600),
Qt.KeepAspectRatio,
Qt.SmoothTransformation
)
self.preview_window.setPixmap(scaled_pixmap)
# 新增扩展屏显示逻辑
if hasattr(self, 'video_window') and self.video_window != self.preview_window:
ext_label = QLabel(self.video_window)
ext_pixmap = pixmap.scaled(
QSize(800, 600),
Qt.KeepAspectRatio,
Qt.SmoothTransformation
)
ext_label.setPixmap(ext_pixmap)
ext_label.setAlignment(Qt.AlignCenter)
ext_label.show()
self.status_bar.setText(f'正在显示: {os.path.basename(file_path)}')
return
except Exception as e:
self.status_bar.setText(f'错误: {str(e)}')
self.show_home_screen()
return
else:
# 如果是单个播放模式且不是图片,先显示首页
if not self.play_mode and not file_path.lower().endswith(('.jpg', '.jpeg', '.png')):
self.show_home_screen()
# 原有的事件监听逻辑
if not self.play_mode:
self.main_player.event_manager().event_attach( # 修正为main_player
vlc.EventType.MediaPlayerEndReached,
self._on_single_play_end
)
media = self.instance.media_new(self.playlist)
# 主播放器设置
self.main_player.stop()
self.main_player.set_media(media)
# 预览播放器设置(静音且独立)
self.preview_player.stop()
self.preview_player.set_media(media)
self.preview_player.audio_set_mute(True)
# 窗口绑定(新增句柄清理)
self.main_player.set_hwnd(0)
self.preview_player.set_hwnd(0)
if self.video_window and self.video_window != self.preview_window:
# 双屏模式:主输出到扩展屏,预览输出到主界面
self.main_player.set_hwnd(self.video_window.winId())
self.preview_player.set_hwnd(self.preview_window.winId())
else:
# 单屏模式:主播放器输出到预览窗口
self.main_player.set_hwnd(self.preview_window.winId())
self.preview_player.set_hwnd(0)
# 同步启动播放
self.main_player.play()
if self.video_window != self.preview_window:
self.preview_player.play()
self.fading_in = True
self.fade_timer.start(self.fade_step_interval)
self.start_fade_in_animation()
# 更新状态和列表选择
self.status_bar.setText(f'正在播放: {os.path.basename(self.playlist)}')
self.playlist_widget.setCurrentRow(index)
def fade_process(self):
"""处理音量渐变过程"""
if self.fading_in:
progress = self.fade_timer.remainingTime() / self.fade_duration
new_volume = int(100 * (1 - progress) ** 3)
self.set_volume(new_volume)
if progress <= 0:
self.fading_in = False
self.fade_timer.stop()
elif self.fading_out:
progress = self.fade_timer.remainingTime() / self.fade_duration
new_volume = int(100 * progress ** 3)
self.set_volume(new_volume)
if progress <= 0:
self.fading_out = False
self.fade_timer.stop()
# 添加200ms延迟后停止播放器
QTimer.singleShot(200, lambda: )
def start_fade_in_animation(self):
"""启动淡入动画"""
self.fade_animation = QPropertyAnimation(self, b"volume")
self.fade_animation.setDuration(self.fade_duration)
self.fade_animation.setStartValue(0)
self.fade_animation.setEndValue(100)
self.fade_animation.setEasingCurve(QEasingCurve.InOutCirc)
self.fade_animation.start()
def update_preview(self):
"""更新预览画面"""
if hasattr(self, 'video_window') and self.video_window != self.preview_window:
# 双屏模式:捕获扩展屏画面
if self.main_player.is_playing():
try:
if self.main_player.video_get_size() > 0:
temp_file = f"preview_{id(self)}.jpg"
if self.main_player.video_take_snapshot(0, temp_file, 0, 0) == 0:
retry = 3
while retry > 0 and not os.path.exists(temp_file):
QApplication.processEvents()
retry -= 1
if os.path.exists(temp_file):
pixmap = QPixmap(temp_file)
if not pixmap.isNull():
target_size = QSize(800, 600)
scaled_pixmap = pixmap.scaled(
target_size,
Qt.KeepAspectRatio,
Qt.SmoothTransformation
)
self.preview_window.setPixmap(scaled_pixmap)
os.remove(temp_file)
except Exception as e:
print(f"预览更新失败: {str(e)}")
else:
# 单屏模式:显示渐变占位图
grad = QLinearGradient(0, 0, self.preview_window.width(), 0)
grad.setColorAt(0, QColor(42, 130, 218))
grad.setColorAt(1, QColor(0, 210, 255))
placeholder = QPixmap(self.preview_window.size())
placeholder.fill(Qt.transparent)
painter = QPainter(placeholder)
painter.setPen(Qt.NoPen)
painter.setBrush(grad)
painter.drawRoundedRect(placeholder.rect(), 10, 10)
painter.setFont(QFont("微软雅黑", 14))
painter.drawText(placeholder.rect(), Qt.AlignCenter, "主画面播放中")
painter.end()
self.preview_window.setPixmap(placeholder)
# 调整截图间隔为500ms
QTimer.singleShot(500, self.update_preview)
def set_position(self, position):
"""设置播放位置"""
# 同时设置两个播放器的进度
if self.main_player.is_playing() and self.preview_player.is_playing():
pos = position / 1000.0
self.main_player.set_position(pos)
self.preview_player.set_position(pos)
def update_media_status(self):
"""更新媒体状态"""
if self.main_player.is_playing():
# 从主播放器获取进度,但保持双播放器同步
position = self.main_player.get_position() * 1000
self.position_slider.setValue(int(position))
# 如果预览播放器不同步则强制同步
if abs(self.preview_player.get_position() - self.main_player.get_position()) > 0.01:
self.preview_player.set_position(self.main_player.get_position())
# 更新预览画面(保持原有逻辑)
if self.mode != "扩展模式" or not hasattr(self, 'ext_screen'):
self.update_preview()
else:
# 检测播放完成
if self.main_player.get_state() == vlc.State.Ended and self.playlist: # 替换为main_player
if self.play_mode: # 连续播放模式
self.next_item()
else: # 单个播放模式
self.stop()
self.show_home_screen()
def toggle_play(self):
if self.main_player.is_playing(): # 替换为main_player
self.main_player.pause() # 替换为main_player
self.status_bar.setText('已暂停')
else:
if self.playlist:
selected = self.playlist_widget.currentRow()
self.play_item(selected if selected != -1 else 0)
def stop(self):
self.main_player.stop()
self.preview_player.stop()
self.current_index = -1
self.show_home_screen()
def show_home_screen(self):
"""显示首页画面"""
# 停止所有播放器
self.main_player.stop()
self.preview_player.stop()
if os.path.exists('index.jpg'):
print("index.jpg 文件存在") # 调试信息
pixmap = QPixmap('index.jpg')
if pixmap.isNull():
print("图片加载失败") # 调试信息
else:
print("图片加载成功") # 调试信息
# 同步设置双屏显示
if len(self.screens) > 1:
scaled_pixmap = pixmap.scaled(QSize(800, 600), Qt.KeepAspectRatio, Qt.SmoothTransformation)
else:
scaled_pixmap = pixmap.scaled(self.preview_window.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
self.preview_window.setPixmap(scaled_pixmap)
if hasattr(self, 'video_window') and self.video_window != self.preview_window:
if len(self.screens) > 1:
ext_pixmap = pixmap.scaled(QSize(800, 600), Qt.KeepAspectRatio, Qt.SmoothTransformation)
else:
ext_pixmap = pixmap.scaled(self.video_window.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
# 使用统一方法设置扩展屏内容
if hasattr(self.video_window, 'setPixmap'):
self.video_window.setPixmap(ext_pixmap)
else:
for child in self.video_window.children():
if isinstance(child, QLabel):
child.setPixmap(ext_pixmap)
label = QLabel(self.video_window)
label.setPixmap(pixmap.scaled(
self.video_window.size(),
Qt.KeepAspectRatio,
Qt.SmoothTransformation
))
label.setAlignment(Qt.AlignCenter)
label.show()
else:
print("index.jpg 文件不存在") # 调试信息
def _hide_taskbar(self):
"""隐藏扩展屏任务栏"""
try:
# 枚举所有窗口寻找扩展屏上的任务栏
def callback(hwnd, extra):
class_name = win32gui.GetClassName(hwnd)
rect = win32gui.GetWindowRect(hwnd)
# 检查是否是任务栏且位于扩展屏区域
if class_name == "Shell_TrayWnd" and self.ext_screen.x <= rect < self.ext_screen.x + self.ext_screen.width:
win32gui.ShowWindow(hwnd, win32con.SW_HIDE)
win32gui.EnumWindows(callback, None)
except Exception as e:
print(f"隐藏任务栏失败: {str(e)}")
def closeEvent(self, event):
"""窗口关闭事件"""
def restore_callback(hwnd, extra):
if win32gui.GetClassName(hwnd) == "Shell_TrayWnd":
win32gui.ShowWindow(hwnd, win32con.SW_SHOW)
win32gui.EnumWindows(restore_callback, None)
self.main_player.stop() # 替换为main_player
if hasattr(self, 'video_window') and self.video_window != self.preview_window:
self.video_window.close()
event.accept()
def _setup_single_image_playback(self):
"""配置单张图片播放"""
self.main_player.stop() # 替换为main_player
self.preview_player.stop() # 新增预览播放器停止
def _on_single_play_end(self, event):
try:
self.stop()
self.show_home_screen()
finally:
# 替换为main_player的事件管理器
self.main_player.event_manager().event_detach(
vlc.EventType.MediaPlayerEndReached
)
def prev_item(self):
"""播放上一项"""
if self.playlist:
new_index = (self.current_index - 1) % len(self.playlist)
self.play_item(new_index)
def next_item(self):
"""播放下一项"""
if self.playlist:
new_index = (self.current_index + 1) % len(self.playlist)
self.play_item(new_index)
def remove_selected(self):
"""删除选中项"""
selected = self.playlist_widget.currentRow()
if selected != -1:
self.playlist.pop(selected)
self.playlist_widget.takeItem(selected)
if not self.playlist:
self.current_index = -1
def clear_playlist(self):
"""清空播放列表"""
self.playlist.clear()
self.playlist_widget.clear()
self.current_index = -1
def save_playlist(self):
"""保存播放列表"""
file_name, _ = QFileDialog.getSaveFileName(self, "保存播放列表", os.getcwd(), "列表文件 (*.list)")
if file_name:
if not file_name.endswith('.list'):
file_name += '.list'
with open(file_name, 'w', encoding='utf-8') as f:
json.dump(self.playlist, f, ensure_ascii=False)
def load_playlist(self):
"""加载播放列表"""
file_name, _ = QFileDialog.getOpenFileName(self, "加载播放列表", os.getcwd(), "列表文件 (*.list)")
if file_name:
try:
with open(file_name, 'r', encoding='utf-8') as f:
self.playlist = json.load(f)
self.playlist_widget.clear()
self.playlist_widget.addItems()
if self.playlist:
self.current_index = 0
except FileNotFoundError:
self.status_bar.setText('播放列表文件不存在')
if __name__ == '__main__':
app = QApplication(sys.argv)
player = ExtendedScreenPlayer()
player.show()
sys.exit(app.exec_())