|
|
|
|
@ -131,6 +131,10 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
# 连接主题切换信号
|
|
|
|
|
theme_manager.theme_changed.connect(self.on_theme_changed)
|
|
|
|
|
|
|
|
|
|
# 设置默认为白色模式(禁用自动检测)
|
|
|
|
|
theme_manager.enable_auto_detection(False)
|
|
|
|
|
theme_manager.set_dark_theme(False)
|
|
|
|
|
|
|
|
|
|
# 应用当前主题
|
|
|
|
|
self.apply_theme()
|
|
|
|
|
|
|
|
|
|
@ -150,30 +154,35 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
"""更新组件样式"""
|
|
|
|
|
colors = theme_manager.get_current_theme_colors()
|
|
|
|
|
|
|
|
|
|
# 更新菜单栏样式
|
|
|
|
|
# 更新菜单栏样式 - 使用微软蓝
|
|
|
|
|
if hasattr(self, 'menubar'):
|
|
|
|
|
self.menubar.setStyleSheet(f"""
|
|
|
|
|
QMenuBar {{
|
|
|
|
|
background-color: {colors['surface']};
|
|
|
|
|
border: 1px solid {colors['border']};
|
|
|
|
|
self.menubar.setStyleSheet("""
|
|
|
|
|
QMenuBar {
|
|
|
|
|
background-color: #0078d7;
|
|
|
|
|
border: 1px solid #005a9e;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
color: {colors['text']};
|
|
|
|
|
}}
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QMenuBar::item {{
|
|
|
|
|
QMenuBar::item {
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
padding: 4px 10px;
|
|
|
|
|
color: {colors['text']};
|
|
|
|
|
}}
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QMenuBar::item:selected {{
|
|
|
|
|
background-color: {colors['surface_hover']};
|
|
|
|
|
}}
|
|
|
|
|
QMenuBar::item:selected {
|
|
|
|
|
background-color: #106ebe;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QMenuBar::item:pressed {{
|
|
|
|
|
background-color: {colors['accent']};
|
|
|
|
|
color: {colors['surface']};
|
|
|
|
|
}}
|
|
|
|
|
QMenuBar::item:pressed {
|
|
|
|
|
background-color: #005a9e;
|
|
|
|
|
color: #ffffff;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#startMenu {
|
|
|
|
|
background-color: white;
|
|
|
|
|
color: #000000;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
# 更新文件菜单样式
|
|
|
|
|
@ -538,6 +547,7 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
|
|
|
|
|
# 开始菜单
|
|
|
|
|
start_menu = menubar.addMenu('开始(S)')
|
|
|
|
|
start_menu.setObjectName("startMenu")
|
|
|
|
|
self.start_menu = start_menu # 保存为实例变量
|
|
|
|
|
|
|
|
|
|
# 撤销
|
|
|
|
|
@ -657,24 +667,30 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
show_weather_action = QAction('显示详细天气', self)
|
|
|
|
|
show_weather_action.triggered.connect(self.show_detailed_weather)
|
|
|
|
|
weather_menu.addAction(show_weather_action)
|
|
|
|
|
#插入
|
|
|
|
|
# 插入菜单
|
|
|
|
|
insert_menu = menubar.addMenu('插入(I)')
|
|
|
|
|
#绘图
|
|
|
|
|
|
|
|
|
|
# 绘图菜单
|
|
|
|
|
paint_menu = menubar.addMenu('绘图(D)')
|
|
|
|
|
#设计
|
|
|
|
|
|
|
|
|
|
# 设计菜单
|
|
|
|
|
design_menu = menubar.addMenu('设计(G)')
|
|
|
|
|
#布局
|
|
|
|
|
|
|
|
|
|
# 布局菜单
|
|
|
|
|
layout_menu = menubar.addMenu('布局(L)')
|
|
|
|
|
#引用
|
|
|
|
|
|
|
|
|
|
# 引用菜单
|
|
|
|
|
reference_menu = menubar.addMenu('引用(R)')
|
|
|
|
|
#邮件
|
|
|
|
|
|
|
|
|
|
# 邮件菜单
|
|
|
|
|
mail_menu = menubar.addMenu('邮件(M)')
|
|
|
|
|
#审阅
|
|
|
|
|
|
|
|
|
|
# 审阅菜单
|
|
|
|
|
review_menu = menubar.addMenu('审阅(W)')
|
|
|
|
|
#视图
|
|
|
|
|
view_menu = menubar.addMenu('视图(V)')
|
|
|
|
|
#开发工具
|
|
|
|
|
|
|
|
|
|
# 开发工具菜单
|
|
|
|
|
developer_menu = menubar.addMenu('开发工具(Q)')
|
|
|
|
|
|
|
|
|
|
# 帮助菜单
|
|
|
|
|
help_menu = menubar.addMenu('帮助(H)')
|
|
|
|
|
|
|
|
|
|
@ -1822,132 +1838,59 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
self.status_bar.showMessage("打印布局功能开发中...", 3000)
|
|
|
|
|
|
|
|
|
|
def set_view_mode(self, mode):
|
|
|
|
|
"""设置视图模式 - 实现文档A和学习文档C的正确交互"""
|
|
|
|
|
"""设置视图模式 - 打开学习模式窗口或切换到打字模式"""
|
|
|
|
|
if mode not in ["typing", "learning"]:
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# 保存当前模式的内容
|
|
|
|
|
current_content = self.text_edit.toPlainText()
|
|
|
|
|
|
|
|
|
|
# 根据当前模式保存特定信息
|
|
|
|
|
if self.view_mode == "typing":
|
|
|
|
|
# 打字模式:保存打字内容到文档A
|
|
|
|
|
self.typing_mode_content = current_content
|
|
|
|
|
print(f"保存打字模式内容到文档A,长度: {len(self.typing_mode_content)}")
|
|
|
|
|
elif self.view_mode == "learning":
|
|
|
|
|
# 学习模式:保存当前学习进度和内容
|
|
|
|
|
self.learning_text = current_content
|
|
|
|
|
if hasattr(self, 'displayed_chars') and self.imported_content:
|
|
|
|
|
self.learning_progress = self.displayed_chars
|
|
|
|
|
print(f"保存学习模式内容,学习进度: {self.learning_progress}/{len(self.imported_content) if self.imported_content else 0}")
|
|
|
|
|
|
|
|
|
|
# 更新模式
|
|
|
|
|
self.view_mode = mode
|
|
|
|
|
self.last_edit_mode = mode
|
|
|
|
|
|
|
|
|
|
# 更新菜单项状态
|
|
|
|
|
self.typing_mode_action.setChecked(mode == "typing")
|
|
|
|
|
self.learning_mode_action.setChecked(mode == "learning")
|
|
|
|
|
|
|
|
|
|
# 临时禁用文本变化信号,避免递归
|
|
|
|
|
self.text_edit.textChanged.disconnect(self.on_text_changed)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
if mode == "typing":
|
|
|
|
|
# 打字模式:显示学习模式下已输入的内容(文档A)
|
|
|
|
|
self.status_bar.showMessage("切换到打字模式 - 显示已输入的内容", 3000)
|
|
|
|
|
|
|
|
|
|
# 设置文档A的内容(学习模式下已输入的内容)
|
|
|
|
|
self.text_edit.clear()
|
|
|
|
|
if hasattr(self, 'learning_progress') and self.learning_progress > 0:
|
|
|
|
|
# 显示学习模式下已输入的内容
|
|
|
|
|
display_text = self.imported_content[:self.learning_progress]
|
|
|
|
|
self.text_edit.setPlainText(display_text)
|
|
|
|
|
else:
|
|
|
|
|
# 如果没有学习进度,显示默认提示
|
|
|
|
|
self.text_edit.setPlainText("请先在学习模式下输入内容")
|
|
|
|
|
if mode == "learning":
|
|
|
|
|
# 学习模式:打开新的学习模式窗口
|
|
|
|
|
try:
|
|
|
|
|
from learning_mode_window import LearningModeWindow
|
|
|
|
|
|
|
|
|
|
# 设置光标位置到文档末尾
|
|
|
|
|
cursor = self.text_edit.textCursor()
|
|
|
|
|
cursor.movePosition(cursor.End)
|
|
|
|
|
self.text_edit.setTextCursor(cursor)
|
|
|
|
|
# 准备传递给学习窗口的参数
|
|
|
|
|
imported_content = ""
|
|
|
|
|
current_position = 0
|
|
|
|
|
|
|
|
|
|
# 重置打字逻辑,准备接受新的输入
|
|
|
|
|
if self.typing_logic:
|
|
|
|
|
# 如果有已导入的内容,传递给学习窗口
|
|
|
|
|
if hasattr(self, 'imported_content') and self.imported_content:
|
|
|
|
|
imported_content = self.imported_content
|
|
|
|
|
if hasattr(self, 'learning_progress') and self.learning_progress > 0:
|
|
|
|
|
# 使用已输入的内容作为打字逻辑的基础
|
|
|
|
|
self.typing_logic.reset(self.imported_content)
|
|
|
|
|
# 设置当前位置到已输入的末尾
|
|
|
|
|
self.typing_logic.current_index = self.learning_progress
|
|
|
|
|
self.typing_logic.typed_chars = self.learning_progress
|
|
|
|
|
else:
|
|
|
|
|
self.typing_logic.reset("")
|
|
|
|
|
current_position = self.learning_progress
|
|
|
|
|
|
|
|
|
|
# 重置显示字符计数
|
|
|
|
|
self.displayed_chars = 0
|
|
|
|
|
# 创建学习模式窗口,直接传递导入内容
|
|
|
|
|
self.learning_window = LearningModeWindow(self, imported_content, current_position)
|
|
|
|
|
|
|
|
|
|
# 重置图片插入记录
|
|
|
|
|
if hasattr(self, 'inserted_images'):
|
|
|
|
|
self.inserted_images.clear()
|
|
|
|
|
# 显示学习模式窗口
|
|
|
|
|
self.learning_window.show()
|
|
|
|
|
|
|
|
|
|
elif mode == "learning":
|
|
|
|
|
# 学习模式:从上次中断的地方继续显示学习文档C的内容
|
|
|
|
|
if not self.imported_content:
|
|
|
|
|
self.status_bar.showMessage("学习模式需要导入文件 - 请先打开一个文件", 3000)
|
|
|
|
|
# 清空文本编辑器,等待导入文件
|
|
|
|
|
self.text_edit.clear()
|
|
|
|
|
if self.typing_logic:
|
|
|
|
|
self.typing_logic.reset("在此输入您的内容...")
|
|
|
|
|
# 重置显示字符计数
|
|
|
|
|
self.displayed_chars = 0
|
|
|
|
|
# 重置图片插入记录
|
|
|
|
|
if hasattr(self, 'inserted_images'):
|
|
|
|
|
self.inserted_images.clear()
|
|
|
|
|
else:
|
|
|
|
|
# 检查是否有保存的学习进度
|
|
|
|
|
if hasattr(self, 'learning_progress') and self.learning_progress > 0:
|
|
|
|
|
self.status_bar.showMessage(f"切换到学习模式 - 从上次中断处继续 ({self.learning_progress}/{len(self.imported_content)})", 3000)
|
|
|
|
|
# 恢复学习进度
|
|
|
|
|
self.displayed_chars = self.learning_progress
|
|
|
|
|
|
|
|
|
|
# 重置打字逻辑,准备接受导入内容
|
|
|
|
|
if self.typing_logic:
|
|
|
|
|
self.typing_logic.reset(self.imported_content)
|
|
|
|
|
|
|
|
|
|
# 获取应该显示的学习文档C的内容部分
|
|
|
|
|
display_text = self.imported_content[:self.displayed_chars]
|
|
|
|
|
|
|
|
|
|
# 设置文本内容
|
|
|
|
|
self.text_edit.clear()
|
|
|
|
|
self.text_edit.setPlainText(display_text)
|
|
|
|
|
|
|
|
|
|
# 设置光标位置到文本末尾
|
|
|
|
|
cursor = self.text_edit.textCursor()
|
|
|
|
|
cursor.movePosition(cursor.End)
|
|
|
|
|
self.text_edit.setTextCursor(cursor)
|
|
|
|
|
|
|
|
|
|
# 重新插入图片
|
|
|
|
|
if hasattr(self, 'inserted_images'):
|
|
|
|
|
self.inserted_images.clear()
|
|
|
|
|
self.insert_images_in_text()
|
|
|
|
|
else:
|
|
|
|
|
self.status_bar.showMessage("切换到学习模式 - 准备显示学习文档C内容", 3000)
|
|
|
|
|
# 重置打字逻辑,准备接受导入内容
|
|
|
|
|
if self.typing_logic:
|
|
|
|
|
self.typing_logic.reset(self.imported_content)
|
|
|
|
|
|
|
|
|
|
# 重置显示字符计数
|
|
|
|
|
self.displayed_chars = 0
|
|
|
|
|
|
|
|
|
|
# 清空文本编辑器,等待用户开始打字
|
|
|
|
|
self.text_edit.clear()
|
|
|
|
|
|
|
|
|
|
# 重置图片插入记录
|
|
|
|
|
if hasattr(self, 'inserted_images'):
|
|
|
|
|
self.inserted_images.clear()
|
|
|
|
|
finally:
|
|
|
|
|
# 重新连接文本变化信号
|
|
|
|
|
self.text_edit.textChanged.connect(self.on_text_changed)
|
|
|
|
|
# 更新菜单状态
|
|
|
|
|
self.learning_mode_action.setChecked(True)
|
|
|
|
|
self.typing_mode_action.setChecked(False)
|
|
|
|
|
|
|
|
|
|
# 切换到打字模式(主窗口保持打字模式)
|
|
|
|
|
self.view_mode = "typing"
|
|
|
|
|
|
|
|
|
|
self.status_bar.showMessage("学习模式窗口已打开", 3000)
|
|
|
|
|
|
|
|
|
|
except ImportError as e:
|
|
|
|
|
QMessageBox.critical(self, "错误", f"无法加载学习模式窗口:\n{str(e)}")
|
|
|
|
|
except Exception as e:
|
|
|
|
|
QMessageBox.critical(self, "错误", f"打开学习模式窗口时出错:\n{str(e)}")
|
|
|
|
|
|
|
|
|
|
elif mode == "typing":
|
|
|
|
|
# 打字模式:保持当前窗口状态
|
|
|
|
|
self.view_mode = "typing"
|
|
|
|
|
self.typing_mode_action.setChecked(True)
|
|
|
|
|
self.learning_mode_action.setChecked(False)
|
|
|
|
|
self.status_bar.showMessage("当前为打字模式", 2000)
|
|
|
|
|
|
|
|
|
|
def on_learning_mode_closed(self):
|
|
|
|
|
"""学习模式窗口关闭时的回调"""
|
|
|
|
|
# 重置菜单状态
|
|
|
|
|
self.learning_mode_action.setChecked(False)
|
|
|
|
|
self.typing_mode_action.setChecked(True)
|
|
|
|
|
self.view_mode = "typing"
|
|
|
|
|
self.status_bar.showMessage("学习模式窗口已关闭", 2000)
|
|
|
|
|
|
|
|
|
|
def set_page_color(self, color):
|
|
|
|
|
"""设置页面颜色"""
|
|
|
|
|
@ -2264,10 +2207,59 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
|
|
|
|
|
def show_about(self):
|
|
|
|
|
"""显示关于对话框"""
|
|
|
|
|
QMessageBox.about(
|
|
|
|
|
self, "关于 MagicWord",
|
|
|
|
|
"MagicWord - 隐私学习软件\n\n"
|
|
|
|
|
"版本: 2.0\n"
|
|
|
|
|
# 创建自定义对话框
|
|
|
|
|
dialog = QDialog(self)
|
|
|
|
|
dialog.setWindowTitle("关于 MagicWord")
|
|
|
|
|
dialog.setModal(True)
|
|
|
|
|
dialog.setFixedSize(500, 400)
|
|
|
|
|
|
|
|
|
|
# 创建布局
|
|
|
|
|
layout = QVBoxLayout()
|
|
|
|
|
|
|
|
|
|
# 添加图标和标题布局
|
|
|
|
|
header_layout = QHBoxLayout()
|
|
|
|
|
|
|
|
|
|
# 添加应用程序图标
|
|
|
|
|
try:
|
|
|
|
|
icon_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "resources", "icons", "app_icon_128X128.png")
|
|
|
|
|
if os.path.exists(icon_path):
|
|
|
|
|
icon_label = QLabel()
|
|
|
|
|
icon_label.setAlignment(Qt.AlignCenter)
|
|
|
|
|
pixmap = QPixmap(icon_path)
|
|
|
|
|
if not pixmap.isNull():
|
|
|
|
|
# 缩放图标到合适大小
|
|
|
|
|
scaled_pixmap = pixmap.scaled(80, 80, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
|
|
|
icon_label.setPixmap(scaled_pixmap)
|
|
|
|
|
header_layout.addWidget(icon_label)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"加载图标失败: {e}")
|
|
|
|
|
|
|
|
|
|
# 添加标题和版本信息
|
|
|
|
|
title_layout = QVBoxLayout()
|
|
|
|
|
title_label = QLabel("MagicWord")
|
|
|
|
|
title_label.setStyleSheet("font-size: 24px; font-weight: bold; color: #0078d7;")
|
|
|
|
|
title_label.setAlignment(Qt.AlignCenter)
|
|
|
|
|
|
|
|
|
|
version_label = QLabel("版本 1.0")
|
|
|
|
|
version_label.setStyleSheet("font-size: 14px; color: #666;")
|
|
|
|
|
version_label.setAlignment(Qt.AlignCenter)
|
|
|
|
|
|
|
|
|
|
title_layout.addWidget(title_label)
|
|
|
|
|
title_layout.addWidget(version_label)
|
|
|
|
|
header_layout.addLayout(title_layout)
|
|
|
|
|
|
|
|
|
|
layout.addLayout(header_layout)
|
|
|
|
|
|
|
|
|
|
# 添加分隔线
|
|
|
|
|
separator = QFrame()
|
|
|
|
|
separator.setFrameShape(QFrame.HLine)
|
|
|
|
|
separator.setFrameShadow(QFrame.Sunken)
|
|
|
|
|
separator.setStyleSheet("color: #ddd;")
|
|
|
|
|
layout.addWidget(separator)
|
|
|
|
|
|
|
|
|
|
# 添加关于信息
|
|
|
|
|
about_text = QLabel(
|
|
|
|
|
"隐私学习软件\n\n"
|
|
|
|
|
"基于 Microsoft Word 界面设计\n\n"
|
|
|
|
|
"功能特色:\n"
|
|
|
|
|
"• 仿Word界面设计\n"
|
|
|
|
|
@ -2276,6 +2268,79 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
"• 实时进度跟踪\n"
|
|
|
|
|
"• 天气和名言显示"
|
|
|
|
|
)
|
|
|
|
|
about_text.setAlignment(Qt.AlignCenter)
|
|
|
|
|
about_text.setStyleSheet("font-size: 12px; line-height: 1.5;")
|
|
|
|
|
layout.addWidget(about_text)
|
|
|
|
|
|
|
|
|
|
# 添加按钮布局
|
|
|
|
|
button_layout = QHBoxLayout()
|
|
|
|
|
button_layout.addStretch() # 添加弹性空间使按钮居中
|
|
|
|
|
|
|
|
|
|
# 添加"沃式烁"按钮
|
|
|
|
|
woshishuo_button = QPushButton("沃式烁")
|
|
|
|
|
woshishuo_button.clicked.connect(lambda: self.show_woshishuo_image())
|
|
|
|
|
button_layout.addWidget(woshishuo_button)
|
|
|
|
|
|
|
|
|
|
# 添加OK按钮
|
|
|
|
|
ok_button = QPushButton("OK")
|
|
|
|
|
ok_button.clicked.connect(dialog.accept)
|
|
|
|
|
button_layout.addWidget(ok_button)
|
|
|
|
|
|
|
|
|
|
button_layout.addStretch() # 添加弹性空间使按钮居中
|
|
|
|
|
|
|
|
|
|
layout.addLayout(button_layout)
|
|
|
|
|
dialog.setLayout(layout)
|
|
|
|
|
|
|
|
|
|
# 显示对话框
|
|
|
|
|
dialog.exec_()
|
|
|
|
|
|
|
|
|
|
def show_woshishuo_image(self):
|
|
|
|
|
"""显示沃式烁图片"""
|
|
|
|
|
try:
|
|
|
|
|
# 图片路径
|
|
|
|
|
image_path = os.path.join(os.path.dirname(__file__), "ui", "114514.png")
|
|
|
|
|
|
|
|
|
|
# 检查图片是否存在
|
|
|
|
|
if not os.path.exists(image_path):
|
|
|
|
|
QMessageBox.warning(self, "错误", "图片文件不存在: 114514.png")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# 创建图片查看对话框
|
|
|
|
|
image_dialog = QDialog(self)
|
|
|
|
|
image_dialog.setWindowTitle("沃式烁")
|
|
|
|
|
image_dialog.setModal(True)
|
|
|
|
|
image_dialog.setFixedSize(500, 400)
|
|
|
|
|
|
|
|
|
|
# 创建布局
|
|
|
|
|
layout = QVBoxLayout()
|
|
|
|
|
|
|
|
|
|
# 添加图片标签
|
|
|
|
|
image_label = QLabel()
|
|
|
|
|
image_label.setAlignment(Qt.AlignCenter)
|
|
|
|
|
image_label.setScaledContents(True)
|
|
|
|
|
|
|
|
|
|
# 加载图片
|
|
|
|
|
pixmap = QPixmap(image_path)
|
|
|
|
|
if pixmap.isNull():
|
|
|
|
|
QMessageBox.warning(self, "错误", "无法加载图片文件")
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# 缩放图片以适应对话框
|
|
|
|
|
scaled_pixmap = pixmap.scaled(450, 300, Qt.KeepAspectRatio, Qt.SmoothTransformation)
|
|
|
|
|
image_label.setPixmap(scaled_pixmap)
|
|
|
|
|
|
|
|
|
|
layout.addWidget(image_label)
|
|
|
|
|
|
|
|
|
|
# 添加关闭按钮
|
|
|
|
|
close_button = QPushButton("关闭")
|
|
|
|
|
close_button.clicked.connect(image_dialog.accept)
|
|
|
|
|
layout.addWidget(close_button)
|
|
|
|
|
|
|
|
|
|
image_dialog.setLayout(layout)
|
|
|
|
|
image_dialog.exec_()
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
QMessageBox.warning(self, "错误", f"显示图片时出错: {str(e)}")
|
|
|
|
|
|
|
|
|
|
def highlight_next_char(self, position, expected_char):
|
|
|
|
|
"""高亮显示下一个期望字符"""
|
|
|
|
|
@ -2337,49 +2402,122 @@ class WordStyleMainWindow(QMainWindow):
|
|
|
|
|
self.status_bar.showMessage("已切换到黑色模式", 2000)
|
|
|
|
|
|
|
|
|
|
def show_image_viewer(self, filename, image_data):
|
|
|
|
|
"""显示图片查看器"""
|
|
|
|
|
"""显示图片查看器 - 图片真正铺满整个窗口上方"""
|
|
|
|
|
try:
|
|
|
|
|
# 创建图片查看窗口
|
|
|
|
|
# 创建自定义图片查看窗口
|
|
|
|
|
viewer = QDialog(self)
|
|
|
|
|
viewer.setWindowTitle(f"图片查看 - {filename}")
|
|
|
|
|
viewer.setModal(False)
|
|
|
|
|
viewer.resize(800, 600)
|
|
|
|
|
|
|
|
|
|
# 创建布局
|
|
|
|
|
layout = QVBoxLayout()
|
|
|
|
|
# 移除窗口边框和标题栏装饰,设置为工具窗口样式
|
|
|
|
|
viewer.setWindowFlags(Qt.Tool | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
|
|
|
|
|
|
|
|
|
|
# 创建滚动区域
|
|
|
|
|
scroll_area = QScrollArea()
|
|
|
|
|
scroll_area.setWidgetResizable(True)
|
|
|
|
|
# 设置窗口背景为黑色,完全无边距
|
|
|
|
|
viewer.setStyleSheet("""
|
|
|
|
|
QDialog {
|
|
|
|
|
background-color: #000000;
|
|
|
|
|
border: none;
|
|
|
|
|
margin: 0px;
|
|
|
|
|
padding: 0px;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
# 创建图片标签
|
|
|
|
|
# 创建布局,完全移除边距
|
|
|
|
|
layout = QVBoxLayout()
|
|
|
|
|
layout.setContentsMargins(0, 0, 0, 0) # 移除布局边距
|
|
|
|
|
layout.setSpacing(0) # 移除组件间距
|
|
|
|
|
layout.setAlignment(Qt.AlignCenter) # 布局居中对齐
|
|
|
|
|
|
|
|
|
|
# 创建图片标签,设置为完全填充模式
|
|
|
|
|
image_label = QLabel()
|
|
|
|
|
image_label.setAlignment(Qt.AlignCenter)
|
|
|
|
|
image_label.setScaledContents(True) # 关键:允许图片缩放以填充标签
|
|
|
|
|
image_label.setMinimumSize(1, 1) # 设置最小尺寸
|
|
|
|
|
image_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # 设置大小策略为扩展
|
|
|
|
|
image_label.setStyleSheet("""
|
|
|
|
|
QLabel {
|
|
|
|
|
border: none;
|
|
|
|
|
margin: 0px;
|
|
|
|
|
padding: 0px;
|
|
|
|
|
background-color: #000000;
|
|
|
|
|
}
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
# 加载图片
|
|
|
|
|
pixmap = QPixmap()
|
|
|
|
|
if pixmap.loadFromData(image_data):
|
|
|
|
|
image_label.setPixmap(pixmap)
|
|
|
|
|
image_label.setScaledContents(False)
|
|
|
|
|
|
|
|
|
|
# 设置标签大小为图片实际大小
|
|
|
|
|
image_label.setFixedSize(pixmap.size())
|
|
|
|
|
else:
|
|
|
|
|
image_label.setText("无法加载图片")
|
|
|
|
|
if not pixmap.loadFromData(image_data):
|
|
|
|
|
self.status_bar.showMessage(f"加载图片失败: {filename}", 3000)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
scroll_area.setWidget(image_label)
|
|
|
|
|
layout.addWidget(scroll_area)
|
|
|
|
|
layout.addWidget(image_label)
|
|
|
|
|
viewer.setLayout(layout)
|
|
|
|
|
|
|
|
|
|
# 添加关闭按钮
|
|
|
|
|
close_btn = QPushButton("关闭")
|
|
|
|
|
close_btn.clicked.connect(viewer.close)
|
|
|
|
|
layout.addWidget(close_btn)
|
|
|
|
|
# 计算位置和大小
|
|
|
|
|
if self:
|
|
|
|
|
parent_geometry = self.geometry()
|
|
|
|
|
screen_geometry = QApplication.primaryScreen().geometry()
|
|
|
|
|
|
|
|
|
|
# 设置窗口宽度与主窗口相同,高度为屏幕高度的40%
|
|
|
|
|
window_width = parent_geometry.width()
|
|
|
|
|
window_height = int(screen_geometry.height() * 0.4)
|
|
|
|
|
|
|
|
|
|
# 计算位置:显示在主窗口正上方
|
|
|
|
|
x = parent_geometry.x()
|
|
|
|
|
y = parent_geometry.y() - window_height
|
|
|
|
|
|
|
|
|
|
# 确保不会超出屏幕边界
|
|
|
|
|
if y < screen_geometry.top():
|
|
|
|
|
y = parent_geometry.y() + 50 # 如果上方空间不足,显示在下方
|
|
|
|
|
|
|
|
|
|
# 调整宽度确保不超出屏幕
|
|
|
|
|
if x + window_width > screen_geometry.right():
|
|
|
|
|
window_width = screen_geometry.right() - x
|
|
|
|
|
|
|
|
|
|
viewer.setGeometry(x, y, window_width, window_height)
|
|
|
|
|
|
|
|
|
|
viewer.setLayout(layout)
|
|
|
|
|
viewer.show()
|
|
|
|
|
|
|
|
|
|
# 关键:强制图片立即填充整个标签区域
|
|
|
|
|
def force_image_fill():
|
|
|
|
|
try:
|
|
|
|
|
if pixmap and not pixmap.isNull():
|
|
|
|
|
# 获取标签的实际大小
|
|
|
|
|
label_size = image_label.size()
|
|
|
|
|
if label_size.width() > 10 and label_size.height() > 10: # 确保尺寸有效
|
|
|
|
|
# 完全填充,忽略宽高比,真正铺满
|
|
|
|
|
scaled_pixmap = pixmap.scaled(
|
|
|
|
|
label_size,
|
|
|
|
|
Qt.IgnoreAspectRatio, # 关键:忽略宽高比,强制填充
|
|
|
|
|
Qt.SmoothTransformation
|
|
|
|
|
)
|
|
|
|
|
image_label.setPixmap(scaled_pixmap)
|
|
|
|
|
print(f"图片已强制缩放至 {label_size.width()}x{label_size.height()}")
|
|
|
|
|
|
|
|
|
|
# 确保标签完全填充布局
|
|
|
|
|
image_label.setMinimumSize(label_size)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
print(f"图片缩放失败: {e}")
|
|
|
|
|
|
|
|
|
|
# 使用多个定时器确保图片正确填充
|
|
|
|
|
from PyQt5.QtCore import QTimer
|
|
|
|
|
QTimer.singleShot(50, force_image_fill) # 50毫秒后执行
|
|
|
|
|
QTimer.singleShot(200, force_image_fill) # 200毫秒后执行
|
|
|
|
|
QTimer.singleShot(1000, force_image_fill) # 1000毫秒后再执行一次
|
|
|
|
|
|
|
|
|
|
# 连接窗口大小变化事件
|
|
|
|
|
viewer.resizeEvent = lambda event: force_image_fill()
|
|
|
|
|
|
|
|
|
|
# 添加点击关闭功能
|
|
|
|
|
def close_viewer():
|
|
|
|
|
viewer.close()
|
|
|
|
|
|
|
|
|
|
image_label.mousePressEvent = lambda event: close_viewer()
|
|
|
|
|
viewer.mousePressEvent = lambda event: close_viewer()
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
self.status_bar.showMessage(f"创建图片查看器失败: {str(e)}", 3000)
|
|
|
|
|
import traceback
|
|
|
|
|
traceback.print_exc()
|
|
|
|
|
|
|
|
|
|
def insert_images_in_text(self):
|
|
|
|
|
"""在文本中插入图片 - 修复图片显示逻辑"""
|
|
|
|
|
|