import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
QHBoxLayout, QPushButton, QLabel, QLineEdit,
QComboBox, QGroupBox, QSpinBox, QColorDialog, QFileDialog,
QTabWidget, QCheckBox, QMessageBox, QSlider, QMenu, QAction,
QGridLayout, QScrollArea, QSplitter, QTextEdit, QSizePolicy)
from PyQt5.QtGui import QPainter, QPen, QFont, QPixmap, QColor, QMouseEvent, QFontMetrics, QIcon
from PyQt5.QtCore import Qt, QSize, QPoint, QRect
from PyQt5.QtPrintSupport import QPrinter, QPrintDialog
import pyttsx3 # 用于文字朗读功能
# 拼音表数据
PINYIN_TABLE = {
"声母": ["b", "p", "m", "f", "d", "t", "n", "l", "g", "k", "h", "j", "q", "x",
"zh", "ch", "sh", "r", "z", "c", "s", "y", "w"],
"韵母": ["a", "o", "e", "i", "u", "ü", "ai", "ei", "ui", "ao", "ou", "iu", "ie",
"üe", "er", "an", "en", "in", "un", "ün", "ang", "eng", "ing", "ong"],
"整体认读音节": ["zhi", "chi", "shi", "ri", "zi", "ci", "si", "yi", "wu", "yu",
"ye", "yue", "yuan", "yin", "yun", "ying"]
}
class PaperWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.grid_type = "田字格"
self.text = ""
self.font_size = 40
self.grid_color = QColor(100, 150, 250)
self.text_color = QColor(50, 50, 50)
self.background_color = QColor(255, 255, 255)
self.grid_size = 60
self.margin = 40
self.rows = 10
self.cols = 8
self.show_text = False
self.show_pinyin = False # 新增:是否显示拼音
self.show_radical = False # 新增:是否显示偏旁部首
self.grid_offset = QPoint(0, 0) # 新增:网格偏移量
self.text_offset = QPoint(0, 0) # 新增:文字偏移量
self.char_rects = [] # 新增:存储每个字符的位置信息
self.tts_engine = None # 延迟初始化语音引擎
def init_tts_engine(self):
"""延迟初始化语音引擎"""
if self.tts_engine is None:
try:
self.tts_engine = pyttsx3.init()
except Exception as e:
print(f"初始化语音引擎失败: {e}")
self.tts_engine = None
def set_grid_type(self, grid_type):
self.grid_type = grid_type
self.update()
def set_text(self, text):
self.text = text
self.update()
def set_font_size(self, size):
self.font_size = size
self.update()
def set_grid_color(self, color):
self.grid_color = color
self.update()
def set_text_color(self, color):
self.text_color = color
self.update()
def set_background_color(self, color):
self.background_color = color
self.update()
def set_grid_size(self, size):
self.grid_size = size
self.update()
def set_rows(self, rows):
self.rows = rows
self.update()
def set_cols(self, cols):
self.cols = cols
self.update()
def set_show_text(self, show):
self.show_text = show
self.update()
def set_show_pinyin(self, show):
self.show_pinyin = show
self.update()
def set_show_radical(self, show):
self.show_radical = show
self.update()
def set_grid_offset(self, dx, dy):
self.grid_offset.setX(dx)
self.grid_offset.setY(dy)
self.update()
def set_text_offset(self, dx, dy):
self.text_offset.setX(dx)
self.text_offset.setY(dy)
self.update()
def paintEvent(self, event):
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing)
# 绘制背景
painter.fillRect(self.rect(), self.background_color)
# 计算起始位置,使网格居中,并应用偏移量
total_width = self.cols * self.grid_size
total_height = self.rows * self.grid_size
start_x = (self.width() - total_width) // 2 + self.grid_offset.x()
start_y = (self.height() - total_height) // 2 + self.grid_offset.y()
# 绘制网格
pen = QPen(self.grid_color)
pen.setWidth(1)
painter.setPen(pen)
if self.grid_type == "田字格":
self.draw_tian_grid(painter, start_x, start_y)
elif self.grid_type == "米字格":
self.draw_mi_grid(painter, start_x, start_y)
elif self.grid_type == "四线格":
self.draw_si_grid(painter, start_x, start_y)
elif self.grid_type == "方格":
self.draw_square_grid(painter, start_x, start_y)
elif self.grid_type == "拼音格":
self.draw_pinyin_grid(painter, start_x, start_y)
# 绘制文字和拼音(仅在show_text为True时)
if self.show_text and self.text:
self.draw_text_and_pinyin(painter, start_x, start_y)
def draw_tian_grid(self, painter, start_x, start_y):
# 绘制外框和内部十字
for row in range(self.rows):
for col in range(self.cols):
x = start_x + col * self.grid_size
y = start_y + row * self.grid_size
# 绘制外框
painter.drawRect(x, y, self.grid_size, self.grid_size)
# 绘制十字
painter.drawLine(x, y + self.grid_size // 2, x + self.grid_size, y + self.grid_size // 2)
painter.drawLine(x + self.grid_size // 2, y, x + self.grid_size // 2, y + self.grid_size)
def draw_mi_grid(self, painter, start_x, start_y):
# 绘制外框和米字
for row in range(self.rows):
for col in range(self.cols):
x = start_x + col * self.grid_size
y = start_y + row * self.grid_size
# 绘制外框
painter.drawRect(x, y, self.grid_size, self.grid_size)
# 绘制十字
painter.drawLine(x, y + self.grid_size // 2, x + self.grid_size, y + self.grid_size // 2)
painter.drawLine(x + self.grid_size // 2, y, x + self.grid_size // 2, y + self.grid_size)
# 绘制对角线
painter.drawLine(x, y, x + self.grid_size, y + self.grid_size)
painter.drawLine(x + self.grid_size, y, x, y + self.grid_size)
def draw_si_grid(self, painter, start_x, start_y):
# 绘制四线格
for row in range(self.rows):
for col in range(self.cols):
x = start_x + col * self.grid_size
y = start_y + row * self.grid_size
# 绘制四条横线
line_spacing = self.grid_size // 3
for i in range(4):
painter.drawLine(x, y + i * line_spacing,
x + self.grid_size, y + i * line_spacing)
def draw_square_grid(self, painter, start_x, start_y):
# 绘制方格
for row in range(self.rows):
for col in range(self.cols):
x = start_x + col * self.grid_size
y = start_y + row * self.grid_size
# 绘制外框
painter.drawRect(x, y, self.grid_size, self.grid_size)
def draw_pinyin_grid(self, painter, start_x, start_y):
# 绘制拼音格(上半部分四线格,下半部分田字格)
for row in range(self.rows):
for col in range(self.cols):
x = start_x + col * self.grid_size
y = start_y + row * self.grid_size
# 绘制上半部分的四线格
line_spacing = self.grid_size // 6
for i in range(4):
painter.drawLine(x, y + i * line_spacing,
x + self.grid_size, y + i * line_spacing)
# 绘制下半部分的田字格
bottom_y = y + self.grid_size // 2
painter.drawRect(x, bottom_y, self.grid_size, self.grid_size // 2)
painter.drawLine(x, bottom_y + self.grid_size // 4,
x + self.grid_size, bottom_y + self.grid_size // 4)
painter.drawLine(x + self.grid_size // 2, bottom_y,
x + self.grid_size // 2, bottom_y + self.grid_size // 2)
def draw_text_and_pinyin(self, painter, start_x, start_y):
self.char_rects = [] # 重置字符位置信息
# 设置文字字体
text_font = QFont("楷体", self.font_size)
painter.setFont(text_font)
painter.setPen(self.text_color)
# 设置拼音字体(稍小)
pinyin_font = QFont("Arial", self.font_size // 3)
# 设置偏旁部首字体(稍小)
radical_font = QFont("楷体", self.font_size // 3)
# 将文本拆分为字符
chars = list(self.text)
char_index = 0
# 在每个格子中心绘制文字和拼音
for row in range(self.rows):
for col in range(self.cols):
if char_index >= len(chars):
return
char = chars[char_index]
x = start_x + col * self.grid_size + self.grid_size // 2
y = start_y + row * self.grid_size + self.grid_size // 2
# 调整文字位置 - 居中并稍微偏下
y_offset = 5 # 向下偏移5像素,使文字更居中
if self.grid_type == "拼音格":
y = start_y + row * self.grid_size + self.grid_size // 4 + y_offset
else:
y = start_y + row * self.grid_size + self.grid_size // 2 + y_offset
# 应用文字偏移
x += self.text_offset.x()
y += self.text_offset.y()
# 绘制拼音(如果启用)
pinyin_rect = QRect() # 初始化pinyin_rect
if self.show_pinyin and char in HANZI_DATA:
painter.setFont(pinyin_font)
pinyin = HANZI_DATA[char]["pinyin"]
pinyin_rect = painter.fontMetrics().boundingRect(pinyin)
painter.drawText(x - pinyin_rect.width() // 2,
y - self.font_size // 2 - 5, # 拼音在文字上方
pinyin)
painter.setFont(text_font)
# 绘制偏旁部首(如果启用)
radical_rect = QRect() # 初始化radical_rect
if self.show_radical and char in HANZI_DATA:
painter.setFont(radical_font)
radical = HANZI_DATA[char]["radical"]
radical_rect = painter.fontMetrics().boundingRect(radical)
# 将偏旁部首绘制在文字的右上角
painter.drawText(x + self.font_size // 4,
y - self.font_size // 4,
radical)
painter.setFont(text_font)
# 居中绘制文字
text_rect = painter.fontMetrics().boundingRect(char)
painter.drawText(x - text_rect.width() // 2,
y + text_rect.height() // 4,
char)
# 存储字符位置信息(用于点击事件)
char_rect = QRect(
x - text_rect.width() // 2,
y - (self.font_size // 2 if self.show_pinyin else 0),
max(text_rect.width(), pinyin_rect.width() if self.show_pinyin and char in HANZI_DATA else 0),
text_rect.height() + (self.font_size // 2 if self.show_pinyin and char in HANZI_DATA else 0)
)
self.char_rects.append((char, char_rect))
char_index += 1
def mousePressEvent(self, event: QMouseEvent):
if not self.show_text or not self.text:
return
# 检查是否点击了某个字符
for char, rect in self.char_rects:
if rect.contains(event.pos()):
self.show_character_info(char)
break
def show_character_info(self, char):
if char in HANZI_DATA:
data = HANZI_DATA[char]
info = f"字符: {char}\n拼音: {data['pinyin']}\n偏旁部首: {data['radical']}\n解释: {data['explanation']}"
QMessageBox.information(self, "字符信息", info)
# 朗读字符和拼音
try:
self.init_tts_engine()
if self.tts_engine:
self.tts_engine.say(char)
self.tts_engine.say(data['pinyin'])
self.tts_engine.runAndWait()
except Exception as e:
print(f"朗读出错: {e}")
else:
QMessageBox.information(self, "字符信息", f"字符 '{char}' 的信息未找到")
def sizeHint(self):
return QSize(600, 800)
class PinyinTableWidget(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.tts_engine = None # 延迟初始化语音引擎
self.init_ui()
def init_tts_engine(self):
"""延迟初始化语音引擎"""
if self.tts_engine is None:
try:
self.tts_engine = pyttsx3.init()
except Exception as e:
print(f"初始化语音引擎失败: {e}")
self.tts_engine = None
def init_ui(self):
# 创建选项卡显示不同类型的拼音
self.tabs = QTabWidget()
# 声母表
initial_tab = QWidget()
self.setup_pinyin_grid(initial_tab, PINYIN_TABLE["声母"], "声母")
self.tabs.addTab(initial_tab, "声母")
# 韵母表
final_tab = QWidget()
self.setup_pinyin_grid(final_tab, PINYIN_TABLE["韵母"], "韵母")
self.tabs.addTab(final_tab, "韵母")
# 整体认读音节表
syllable_tab = QWidget()
self.setup_pinyin_grid(syllable_tab, PINYIN_TABLE["整体认读音节"], "整体认读音节")
self.tabs.addTab(syllable_tab, "整体认读音节")
# 设置主布局
main_layout = QVBoxLayout(self)
main_layout.addWidget(self.tabs)
def setup_pinyin_grid(self, tab, pinyin_list, title):
# 创建滚动区域
scroll_area = QScrollArea()
scroll_area.setWidgetResizable(True)
# 创建容器部件
container = QWidget()
grid_layout = QGridLayout(container)
# 添加拼音按钮
row, col = 0, 0
for pinyin in pinyin_list:
btn = QPushButton(pinyin)
btn.setFixedSize(60, 60)
btn.setStyleSheet("""
QPushButton {
font-size: 18px;
font-weight: bold;
background-color: #89c2ff;
border: none;
border-radius: 8px;
color: white;
}
QPushButton:hover {
background-color: #5fa3ff;
}
""")
btn.clicked.connect(lambda checked, p=pinyin: self.play_pinyin(p))
grid_layout.addWidget(btn, row, col)
col += 1
if col > 4: # 每行5个按钮
col = 0
row += 1
# 设置滚动区域的内容
scroll_area.setWidget(container)
# 设置选项卡布局
tab_layout = QVBoxLayout(tab)
tab_layout.addWidget(QLabel(f"{title}表"))
tab_layout.addWidget(scroll_area)
def play_pinyin(self, pinyin):
# 播放拼音
try:
self.init_tts_engine()
if self.tts_engine:
self.tts_engine.say(pinyin)
self.tts_engine.runAndWait()
except Exception as e:
print(f"朗读出错: {e}")
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("儿童字格生成器")
self.setGeometry(100, 100, 1200, 800)
# 设置可爱的样式
self.setStyleSheet("""
QMainWindow {
background-color: #f0f9ff;
}
QGroupBox {
font-weight: bold;
border: 2px solid #89c2ff;
border-radius: 8px;
margin-top: 1ex;
background-color: #e6f3ff;
}
QGroupBox::title {
subcontrol-origin: margin;
left: 10px;
padding: 0 5px 0 5px;
color: #2b6cb0;
}
QPushButton {
background-color: #89c2ff;
border: none;
border-radius: 8px;
color: white;
padding: 8px;
font-weight: bold;
}
QPushButton:hover {
background-color: #5fa3ff;
}
QPushButton:pressed {
background-color: #3b82f6;
}
QLabel {
color: #2b6cb0;
font-weight: bold;
}
QLineEdit {
border: 2px solid #89c2ff;
border-radius: 5px;
padding: 5px;
background-color: white;
}
QComboBox, QSpinBox {
border: 2px solid #89c2ff;
border-radius: 5px;
padding: 5px;
background-color: white;
}
QTabWidget::pane {
border: 2px solid #89c2ff;
border-radius: 8px;
background-color: #e6f3ff;
}
QTabBar::tab {
background-color: #c7e0ff;
border: 2px solid #89c2ff;
border-bottom: none;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
padding: 8px;
margin-right: 2px;
}
QTabBar::tab:selected {
background-color: #89c2ff;
color: white;
}
QSlider::groove:horizontal {
border: 1px solid #89c2ff;
height: 8px;
background: #e6f3ff;
border-radius: 4px;
}
QSlider::handle:horizontal {
background: #89c2ff;
border: 1px solid #5fa3ff;
width: 18px;
margin: -5px 0;
border-radius: 9px;
}
""")
# 创建中央部件和布局
central_widget = QWidget()
self.setCentralWidget(central_widget)
main_layout = QHBoxLayout(central_widget)
# 创建选项卡
self.tabs = QTabWidget()
main_layout.addWidget(self.tabs)
# 创建空白模版选项卡
self.blank_template_tab = QWidget()
self.setup_blank_template_tab()
self.tabs.addTab(self.blank_template_tab, "空白字格模版")
# 创建带文字模版选项卡
self.text_template_tab = QWidget()
self.setup_text_template_tab()
self.tabs.addTab(self.text_template_tab, "带文字字格模版")
# 创建文字朗读和拼音设置模版
self.tts_pinyin_tab = QWidget()
self.setup_tts_pinyin_tab()
self.tabs.addTab(self.tts_pinyin_tab, "文字朗读和拼音设置")
# 创建拼音表选项卡
self.pinyin_table_tab = QWidget()
self.setup_pinyin_table_tab()
self.tabs.addTab(self.pinyin_table_tab, "拼音表")
# 创建纸张显示部件
self.paper_widget = PaperWidget()
main_layout.addWidget(self.paper_widget, 2)
def setup_blank_template_tab(self):
layout = QVBoxLayout(self.blank_template_tab)
# 字格类型选择
grid_type_layout = QHBoxLayout()
grid_type_layout.addWidget(QLabel("字格类型:"))
self.grid_type_combo = QComboBox()
self.grid_type_combo.addItems(["田字格", "米字格", "四线格", "方格", "拼音格"])
self.grid_type_combo.currentTextChanged.connect(self.update_grid_type)
grid_type_layout.addWidget(self.grid_type_combo)
layout.addLayout(grid_type_layout)
# 网格尺寸设置
grid_size_group = QGroupBox("网格尺寸设置")
grid_size_layout = QVBoxLayout(grid_size_group)
# 网格大小
size_layout = QHBoxLayout()
size_layout.addWidget(QLabel("网格大小:"))
self.grid_size_spin = QSpinBox()
self.grid_size_spin.setRange(20, 100)
self.grid_size_spin.setValue(60)
self.grid_size_spin.valueChanged.connect(self.update_grid_size)
size_layout.addWidget(self.grid_size_spin)
grid_size_layout.addLayout(size_layout)
# 网格行数
rows_layout = QHBoxLayout()
rows_layout.addWidget(QLabel("行数:"))
self.rows_spin = QSpinBox()
self.rows_spin.setRange(1, 20)
self.rows_spin.setValue(10)
self.rows_spin.valueChanged.connect(self.update_rows)
rows_layout.addWidget(self.rows_spin)
grid_size_layout.addLayout(rows_layout)
# 网格列数
cols_layout = QHBoxLayout()
cols_layout.addWidget(QLabel("列数:"))
self.cols_spin = QSpinBox()
self.cols_spin.setRange(1, 20)
self.cols_spin.setValue(8)
self.cols_spin.valueChanged.connect(self.update_cols)
cols_layout.addWidget(self.cols_spin)
grid_size_layout.addLayout(cols_layout)
layout.addWidget(grid_size_group)
# 颜色选择
grid_color_btn = QPushButton("选择网格颜色")
grid_color_btn.clicked.connect(self.choose_grid_color)
layout.addWidget(grid_color_btn)
bg_color_btn = QPushButton("选择背景颜色")
bg_color_btn.clicked.connect(self.choose_bg_color)
layout.addWidget(bg_color_btn)
# 功能按钮
print_btn = QPushButton("打印")
print_btn.clicked.connect(self.print_paper)
layout.addWidget(print_btn)
save_btn = QPushButton("保存为图片")
save_btn.clicked.connect(self.save_as_image)
layout.addWidget(save_btn)
# 添加弹性空间
layout.addStretch()
def setup_text_template_tab(self):
layout = QVBoxLayout(self.text_template_tab)
# 字格类型选择和显示文字选项
grid_type_layout = QHBoxLayout()
grid_type_layout.addWidget(QLabel("字格类型:"))
self.text_grid_type_combo = QComboBox()
self.text_grid_type_combo.addItems(["田字格", "米字格", "四线格", "方格", "拼音格"])
self.text_grid_type_combo.currentTextChanged.connect(self.update_grid_type)
grid_type_layout.addWidget(self.text_grid_type_combo)
# 显示文字复选框
self.show_text_checkbox = QCheckBox("显示文字")
self.show_text_checkbox.setChecked(True)
self.show_text_checkbox.stateChanged.connect(self.update_show_text)
grid_type_layout.addWidget(self.show_text_checkbox)
layout.addLayout(grid_type_layout)
# 文字输入设置
text_group = QGroupBox("文字输入设置")
text_layout = QVBoxLayout(text_group)
# 文字输入
input_layout = QHBoxLayout()
input_layout.addWidget(QLabel("输入文字:"))
self.text_input = QLineEdit()
self.text_input.textChanged.connect(self.update_text)
input_layout.addWidget(self.text_input)
text_layout.addLayout(input_layout)
layout.addWidget(text_group)
# 文字位置调整
text_position_group = QGroupBox("文字位置调整")
text_position_layout = QVBoxLayout(text_position_group)
# 水平位置调整
text_h_layout = QHBoxLayout()
text_h_layout.addWidget(QLabel("左右:"))
self.text_h_slider = QSlider(Qt.Horizontal)
self.text_h_slider.setRange(-50, 50)
self.text_h_slider.setValue(0)
self.text_h_slider.valueChanged.connect(self.update_text_position)
text_h_layout.addWidget(self.text_h_slider)
text_position_layout.addLayout(text_h_layout)
# 垂直位置调整
text_v_layout = QHBoxLayout()
text_v_layout.addWidget(QLabel("上下:"))
self.text_v_slider = QSlider(Qt.Horizontal)
self.text_v_slider.setRange(-50, 50)
self.text_v_slider.setValue(0)
self.text_v_slider.valueChanged.connect(self.update_text_position)
text_v_layout.addWidget(self.text_v_slider)
text_position_layout.addLayout(text_v_layout)
# 重置文字位置按钮
reset_text_btn = QPushButton("重置文字位置")
reset_text_btn.clicked.connect(self.reset_text_position)
text_position_layout.addWidget(reset_text_btn)
layout.addWidget(text_position_group)
# 字体设置
font_group = QGroupBox("字体设置")
font_layout = QVBoxLayout(font_group)
# 字体大小
font_size_layout = QHBoxLayout()
font_size_layout.addWidget(QLabel("字体大小:"))
self.font_size_spin = QSpinBox()
self.font_size_spin.setRange(10, 100)
self.font_size_spin.setValue(40)
self.font_size_spin.valueChanged.connect(self.update_font_size)
font_size_layout.addWidget(self.font_size_spin)
font_layout.addLayout(font_size_layout)
layout.addWidget(font_group)
# 网格尺寸设置
grid_size_group = QGroupBox("网格尺寸设置")
grid_size_layout = QVBoxLayout(grid_size_group)
# 网格大小
size_layout = QHBoxLayout()
size_layout.addWidget(QLabel("网格大小:"))
self.text_grid_size_spin = QSpinBox()
self.text_grid_size_spin.setRange(20, 100)
self.text_grid_size_spin.setValue(60)
self.text_grid_size_spin.valueChanged.connect(self.update_grid_size)
size_layout.addWidget(self.text_grid_size_spin)
grid_size_layout.addLayout(size_layout)
# 网格行数
rows_layout = QHBoxLayout()
rows_layout.addWidget(QLabel("行数:"))
self.text_rows_spin = QSpinBox()
self.text_rows_spin.setRange(1, 20)
self.text_rows_spin.setValue(10)
self.text_rows_spin.valueChanged.connect(self.update_rows)
rows_layout.addWidget(self.text_rows_spin)
grid_size_layout.addLayout(rows_layout)
# 网格列数
cols_layout = QHBoxLayout()
cols_layout.addWidget(QLabel("列数:"))
self.text_cols_spin = QSpinBox()
self.text_cols_spin.setRange(1, 20)
self.text_cols_spin.setValue(8)
self.text_cols_spin.valueChanged.connect(self.update_cols)
cols_layout.addWidget(self.text_cols_spin)
grid_size_layout.addLayout(cols_layout)
layout.addWidget(grid_size_group)
# 颜色选择
grid_color_btn = QPushButton("选择网格颜色")
grid_color_btn.clicked.connect(self.choose_grid_color)
layout.addWidget(grid_color_btn)
text_color_btn = QPushButton("选择文字颜色")
text_color_btn.clicked.connect(self.choose_text_color)
layout.addWidget(text_color_btn)
bg_color_btn = QPushButton("选择背景颜色")
bg_color_btn.clicked.connect(self.choose_bg_color)
layout.addWidget(bg_color_btn)
# 功能按钮
print_btn = QPushButton("打印")
print_btn.clicked.connect(self.print_paper)
layout.addWidget(print_btn)
save_btn = QPushButton("保存为图片")
save_btn.clicked.connect(self.save_as_image)
layout.addWidget(save_btn)
clear_btn = QPushButton("清空文字")
clear_btn.clicked.connect(self.clear_text)
layout.addWidget(clear_btn)
# 添加弹性空间
layout.addStretch()
def setup_tts_pinyin_tab(self):
layout = QVBoxLayout(self.tts_pinyin_tab)
# 朗读设置
tts_group = QGroupBox("朗读设置")
tts_layout = QVBoxLayout(tts_group)
# 文字输入和朗读按钮
tts_input_layout = QHBoxLayout()
tts_input_layout.addWidget(QLabel("输入文字:"))
self.tts_text_input = QLineEdit()
tts_input_layout.addWidget(self.tts_text_input)
# 喇叭图标按钮
self.speak_button = QPushButton()
self.speak_button.setIcon(QIcon.fromTheme("audio-volume-medium"))
self.speak_button.setToolTip("朗读文字和拼音")
self.speak_button.clicked.connect(self.speak_text_with_pinyin)
tts_input_layout.addWidget(self.speak_button)
tts_layout.addLayout(tts_input_layout)
# 测试按钮
tts_test_btn = QPushButton("测试朗读功能")
tts_test_btn.clicked.connect(self.test_tts)
tts_layout.addWidget(tts_test_btn)
# 音量设置
tts_volume_layout = QHBoxLayout()
tts_volume_layout.addWidget(QLabel("音量:"))
self.tts_volume_slider = QSlider(Qt.Horizontal)
self.tts_volume_slider.setRange(0, 100)
self.tts_volume_slider.setValue(70)
self.tts_volume_slider.valueChanged.connect(self.update_tts_volume)
tts_volume_layout.addWidget(self.tts_volume_slider)
tts_layout.addLayout(tts_volume_layout)
# 语速设置
tts_rate_layout = QHBoxLayout()
tts_rate_layout.addWidget(QLabel("语速:"))
self.tts_rate_slider = QSlider(Qt.Horizontal)
self.tts_rate_slider.setRange(0, 200)
self.tts_rate_slider.setValue(130)
self.tts_rate_slider.valueChanged.connect(self.update_tts_rate)
tts_rate_layout.addWidget(self.tts_rate_slider)
tts_layout.addLayout(tts_rate_layout)
layout.addWidget(tts_group)
# 拼音设置
pinyin_group = QGroupBox("拼音设置")
pinyin_layout = QVBoxLayout(pinyin_group)
self.show_pinyin_checkbox_tts = QCheckBox("显示拼音")
self.show_pinyin_checkbox_tts.stateChanged.connect(self.update_show_pinyin)
pinyin_layout.addWidget(self.show_pinyin_checkbox_tts)
self.show_radical_checkbox_tts = QCheckBox("显示偏旁部首")
self.show_radical_checkbox_tts.stateChanged.connect(self.update_show_radical)
pinyin_layout.addWidget(self.show_radical_checkbox_tts)
layout.addWidget(pinyin_group)
# 添加弹性空间
layout.addStretch()
def setup_pinyin_table_tab(self):
layout = QVBoxLayout(self.pinyin_table_tab)
# 创建拼音表部件
self.pinyin_table_widget = PinyinTableWidget()
layout.addWidget(self.pinyin_table_widget)
def speak_text_with_pinyin(self):
text = self.tts_text_input.text()
if text:
# 更新字格显示
self.paper_widget.set_text(text)
self.paper_widget.set_show_text(True)
self.show_text_checkbox.setChecked(True)
# 构建朗读字符串(文字和拼音)
speak_text = ""
for char in text:
speak_text += char + " "
if char in HANZI_DATA:
speak_text += HANZI_DATA[char]['pinyin'] + " "
# 朗读文字和拼音
try:
self.paper_widget.init_tts_engine()
if self.paper_widget.tts_engine:
self.paper_widget.tts_engine.say(speak_text)
self.paper_widget.tts_engine.runAndWait()
except Exception as e:
QMessageBox.warning(self, "朗读错误", f"朗读功能出错: {e}")
def test_tts(self):
try:
self.paper_widget.init_tts_engine()
if self.paper_widget.tts_engine:
self.paper_widget.tts_engine.say("测试朗读功能")
self.paper_widget.tts_engine.runAndWait()
except Exception as e:
QMessageBox.warning(self, "朗读错误", f"朗读功能出错: {e}")
def update_tts_volume(self, volume):
self.paper_widget.init_tts_engine()
if self.paper_widget.tts_engine:
self.paper_widget.tts_engine.setProperty('volume', volume / 100)
def update_tts_rate(self, rate):
self.paper_widget.init_tts_engine()
if self.paper_widget.tts_engine:
self.paper_widget.tts_engine.setProperty('rate', rate)
def update_show_pinyin(self, state):
self.paper_widget.set_show_pinyin(state == Qt.Checked)
def update_show_radical(self, state):
self.paper_widget.set_show_radical(state == Qt.Checked)
def update_text_position(self):
dx = self.text_h_slider.value()
dy = self.text_v_slider.value()
self.paper_widget.set_text_offset(dx, dy)
def reset_text_position(self):
self.text_h_slider.setValue(0)
self.text_v_slider.setValue(0)
self.paper_widget.set_text_offset(0, 0)
def update_rows(self, rows):
self.paper_widget.set_rows(rows)
def update_cols(self, cols):
self.paper_widget.set_cols(cols)
def update_grid_type(self, grid_type):
self.paper_widget.set_grid_type(grid_type)
def update_text(self, text):
self.paper_widget.set_text(text)
def update_font_size(self, size):
self.paper_widget.set_font_size(size)
def update_grid_size(self, size):
self.paper_widget.set_grid_size(size)
def update_show_text(self, state):
self.paper_widget.set_show_text(state == Qt.Checked)
def choose_grid_color(self):
color = QColorDialog.getColor()
if color.isValid():
self.paper_widget.set_grid_color(color)
def choose_text_color(self):
color = QColorDialog.getColor()
if color.isValid():
self.paper_widget.set_text_color(color)
def choose_bg_color(self):
color = QColorDialog.getColor()
if color.isValid():
self.paper_widget.set_background_color(color)
def print_paper(self):
printer = QPrinter(QPrinter.HighResolution)
printer.setPageSize(QPrinter.A4)
printer.setOrientation(QPrinter.Portrait)
print_dialog = QPrintDialog(printer, self)
if print_dialog.exec_() == QPrintDialog.Accepted:
painter = QPainter(printer)
rect = printer.pageRect()
self.paper_widget.render(painter)
painter.end()
def save_as_image(self):
file_path, _ = QFileDialog.getSaveFileName(
self, "保存图片", "", "PNG图片 (*.png);;JPEG图片 (*.jpg *.jpeg)"
)
if file_path:
pixmap = QPixmap(self.paper_widget.size())
self.paper_widget.render(pixmap)
pixmap.save(file_path)
def clear_text(self):
self.text_input.clear()
self.paper_widget.set_text("")
if __name__ == "__main__":
app = QApplication(sys.argv)
# 设置应用程序字体
font = QFont("微软雅黑", 10)
app.setFont(font)
window = MainWindow()
window.show()
sys.exit(app.exec_())
1.修改“拼音格”模版高度,高度要加大,格式不能变形。要和米字格一样的大小。2.重新输入文字以后,重新语音朗读出来。3.删除朗读和拼音设置中的拼音设置功能。
最新发布