ChatGPT在输出数学公式的时候是正常的,但是粘贴到word、粘贴到MarkDown笔记里就直接变成了一堆代码,其实是有办法解决的,本篇文章主要解决一下无法复制问题
目录
一、问题复现
ChatGPT输出的信息是这样的(很工正):
复制到word中是这样的:
复制到MakeDown中是这样的:
如何让复制出来的效果跟ChatGPT展示的效果一样是个问题,今天主要来解决这个。
二、效果展示
(代码文章里放有,当然,我也打包了exe程序放在文章末尾,有需要自取)
1. 测试案例
接下来我们从ChatGPT中复制过来这么一段文字,包含字符和数学算式:
如果要将您提供的数学公式格式化为内联的LaTeX样式,可以这样写:
在极坐标系中,两个极坐标点相加的含义是将它们表示的向量相加。每个极坐标点可以用一个长度(模)和一个方向角(角度或弧度)来描述。
具体地说,如果有两个极坐标点 \( (r_1, \theta_1) \) 和 \( (r_2, \theta_2) \),它们分别表示长度为 \( r_1 \) 和 \( r_2 \),方向角为 \( \theta_1 \) 和 \( \theta_2 \) 的向量。
将这两个向量相加得到的结果向量的极坐标可以通过以下公式计算:
\[ (r_1, \theta_1) + (r_2, \theta_2) = \left( \sqrt{r_1^2 + r_2^2 + 2r_1r_2\cos(\theta_2 - \theta_1)}, \ \theta_1 + \tan^{-1} \left( \frac{r_2\sin(\theta_2 - \theta_1)}{r_1 + r_2\cos(\theta_2 - \theta_1)} \right) \right) \]
这里,\( \sqrt{r_1^2 + r_2^2 + 2r_1r_2\cos(\theta_2 - \theta_1)} \) 是结果向量的长度,\( \theta_1 + \tan^{-1} \left( \frac{r_2\sin(\theta_2 - \theta_1)}{r_1 + r_2\cos(\theta_2 - \theta_1)} \right) \) 是结果向量的方向角。
因此,两个极坐标点相加的含义是将它们表示的两个向量进行向量加法,得到一个新的向量,其长度和方向角是根据上述公式计算得到的。
这样,您可以在LaTeX中内联地显示这个公式。
很明显,复制过来直接就成了这样,文字、代码、符号一堆。
2. 开始转换
(1)运行程序
我设置了一个输入框、两个转换按钮、一个重置按钮、一个输出框、一个复制按钮,对了左下角有信息提示,简单提示一下按钮的功能,当然,最后点击复制后,如果复制成功,可以在左下角看到提示。
(2)将ChatGPT的内容粘贴进来
注意,是使用ChatGPT左下角的复制选项,不要手动框选复制,框选复制的公式没法恢复。
复制后就可以在程序的输入框里边复制,像这样:
(3)点击转换为MarkDown
点击之后就可以在下边的文本框里看到转换后的文字信息,为了方便大家对应原文本里的公式,我并没有把公式单独列出来。
(4)点击复制就可以了
因为我用的CSDN编辑器是MarkDown的,在这里就直接复制进来让大家看下效果:
将这两个向量相加得到的结果向量的极坐标可以通过以下公式计算:
(
r
1
,
θ
1
)
+
(
r
2
,
θ
2
)
=
(
r
1
2
+
r
2
2
+
2
r
1
r
2
cos
(
θ
2
−
θ
1
)
,
θ
1
+
tan
−
1
(
r
2
sin
(
θ
2
−
θ
1
)
r
1
+
r
2
cos
(
θ
2
−
θ
1
)
)
)
(r_1, \theta_1) + (r_2, \theta_2) = \left( \sqrt{r_1^2 + r_2^2 + 2r_1r_2\cos(\theta_2 - \theta_1)}, \ \theta_1 + \tan^{-1} \left( \frac{r_2\sin(\theta_2 - \theta_1)}{r_1 + r_2\cos(\theta_2 - \theta_1)} \right) \right)
(r1,θ1)+(r2,θ2)=(r12+r22+2r1r2cos(θ2−θ1), θ1+tan−1(r1+r2cos(θ2−θ1)r2sin(θ2−θ1)))
这里,
r 1 2 + r 2 2 + 2 r 1 r 2 cos ( θ 2 − θ 1 ) \sqrt{r_1^2 + r_2^2 + 2r_1r_2\cos(\theta_2 - \theta_1)} r12+r22+2r1r2cos(θ2−θ1)
是结果向量的长度,
θ 1 + tan − 1 ( r 2 sin ( θ 2 − θ 1 ) r 1 + r 2 cos ( θ 2 − θ 1 ) ) \theta_1 + \tan^{-1} \left( \frac{r_2\sin(\theta_2 - \theta_1)}{r_1 + r_2\cos(\theta_2 - \theta_1)} \right) θ1+tan−1(r1+r2cos(θ2−θ1)r2sin(θ2−θ1))
是结果向量的方向角。
因此,两个极坐标点相加的含义是将它们表示的两个向量进行向量加法,得到一个新的向量,其长度和方向角是根据上述公式计算得到的。
忙活了大半天,结果很完美。
(5)点击转化为LaTeX
如果想将公式复制到Word、PPT、Excel,需要使用这个功能,比如我这里有句话:
如果要将您提供的数学公式格式化为内联的LaTeX样式,可以这样写:
\((r_1, \theta_1) + (r_2, \theta_2) = \left(r_1^2 + r_2^2 + 2r_1r_2 \cos(\theta_2 - \theta_1), \ \theta_1 + \tan^{-1} \left(\frac{r_1 + r_2 \cos(\theta_2 - \theta_1)}{r_2 \sin(\theta_2 - \theta_1)} \right)\right)\)
这样,您可以在LaTeX中内联地显示这个公式。
复制进去后是这样的:
点击“转化为LaTeX”可以看到这些内容:
选择复制我们需要的部分:
打开word后按下Alt + =(word里边的LaTeX编辑器),会出来一个这个:
将复制的内容粘贴进去,按下回车就好了:
在PPT和Excel中插入LaTeX时需要使用一些插件,如MathType(官网),然后根据操作将LaTex代码插入进去就可以了(若有问题见文章末尾联系渠道)。
(6)其他操作
当然,这个重置按钮可是我精心为大家设置的,如果经常需要转化,可以在每次转化前点一下重置按钮,非常方便。
三、代码展示
这里放一下我调试好的代码,若想在这个基础上继续完善欢迎自取。
import re
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QTextEdit, QPushButton, QWidget, \
QStatusBar
from PyQt5.QtCore import Qt, QEvent
from PyQt5.QtGui import QFont
class FormulaConverterApp(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("ChatGPT公式内容转换")
self.setGeometry(100, 100, 720, 540)
self.statusBar = QStatusBar()
self.setStatusBar(self.statusBar)
self.statusBar.setFont(QFont("微软雅黑", 12))
# Set up the main layout
main_layout = QVBoxLayout()
main_layout.setContentsMargins(20, 20, 20, 20) # Set margins around the layout
main_layout.setSpacing(5) # Set spacing between widgets in the layout
# Input field
self.input_field = QTextEdit("请复制ChatGPT的公式粘贴在这里")
self.input_field.setFixedHeight(150)
self.input_field.setFont(QFont("微软雅黑", 12))
self.input_field.setStyleSheet("color: black;")
self.input_field.installEventFilter(self)
self.set_shadow_effect(self.input_field)
main_layout.addWidget(self.input_field)
# Buttons
button_layout = QHBoxLayout()
button_layout.setSpacing(5) # Set spacing between buttons
self.md_button = QPushButton("转换为Markdown")
self.md_button.clicked.connect(self.convert_to_markdown)
self.md_button.setToolTip("可以直接粘贴到MarkDown笔记")
self.set_shadow_effect(self.md_button)
button_layout.addWidget(self.md_button)
self.latex_button = QPushButton("转化为LaTeX")
self.latex_button.clicked.connect(self.convert_to_latex)
self.latex_button.setToolTip("可以直接粘贴到Word、PPT、Excel")
self.set_shadow_effect(self.latex_button)
button_layout.addWidget(self.latex_button)
self.reset_button = QPushButton("重置")
self.reset_button.clicked.connect(self.reset_input)
self.reset_button.setToolTip("清空输入")
self.set_shadow_effect(self.reset_button)
button_layout.addWidget(self.reset_button)
main_layout.addLayout(button_layout)
# Text display
self.text_display = QTextEdit("转换后的信息将在这里展示")
self.text_display.setFixedHeight(150)
self.text_display.setFont(QFont("微软雅黑", 12))
self.text_display.setStyleSheet("color: black;")
self.text_display.installEventFilter(self)
self.set_shadow_effect(self.text_display)
main_layout.addWidget(self.text_display)
# Copy button
self.copy_button = QPushButton("复制")
self.copy_button.clicked.connect(self.copy_to_clipboard)
self.set_shadow_effect(self.copy_button)
main_layout.addWidget(self.copy_button)
# Set the main widget and layout
container = QWidget()
container.setLayout(main_layout)
self.setCentralWidget(container)
# Connect button hover events to status bar messages
self.md_button.installEventFilter(self)
self.latex_button.installEventFilter(self)
self.reset_button.installEventFilter(self)
# Apply styles
self.apply_styles()
def apply_styles(self):
self.setStyleSheet("""
QMainWindow {
background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 #87CEEB, stop:1 #1E90FF);
}
QTextEdit {
color: black;
font-family: "微软雅黑";
font-size: 10pt;
border: none;
background-color: #f0f0f0;
padding: 20px;
border-radius: 10px;
}
QPushButton {
font-family: "微软雅黑";
font-size: 12pt;
height: 40px;
border: none;
background-color: #f0f0f0;
padding: 10px;
border-radius: 10px;
}
QPushButton:hover {
background-color: #dcdcdc;
}
QPushButton:pressed {
background-color: #c0c0c0;
}
QPushButton:focus {
outline: none;
}
""")
def eventFilter(self, source, event):
if event.type() == QEvent.Enter:
if source == self.md_button:
self.statusBar.showMessage("第五提示:可以直接粘贴到MarkDown笔记")
elif source == self.latex_button:
self.statusBar.showMessage("第五提示:可以直接粘贴到Word、PPT、Excel")
elif source == self.reset_button:
self.statusBar.showMessage("第五提示:清空输入")
elif event.type() == QEvent.Leave:
self.statusBar.clearMessage()
elif event.type() == QEvent.FocusIn:
if source in [self.input_field, self.text_display]:
if source.toPlainText() in ["请复制ChatGPT的公式粘贴在这里", "转换后的信息将在这里展示"]:
source.clear()
source.setStyleSheet("color: black;")
elif event.type() == QEvent.FocusOut:
if source == self.input_field and source.toPlainText().strip() == "":
source.setText("请复制ChatGPT的公式粘贴在这里")
source.setStyleSheet("color: black;")
elif source == self.text_display and source.toPlainText().strip() == "":
source.setText("转换后的信息将在这里展示")
source.setStyleSheet("color: black;")
return super().eventFilter(source, event)
def set_shadow_effect(self, widget):
widget.setGraphicsEffect(None)
shadow = """
border: 2px solid #c0c0c0;
border-radius: 10px;
background-color: #f0f0f0;
box-shadow: 3px 3px 10px #aaaaaa;
"""
widget.setStyleSheet(widget.styleSheet() + shadow)
def contains_chinese_characters(self, input_str):
for char in input_str:
if '\u4e00' <= char <= '\u9fff':
return True
return False
def convert_to_markdown(self):
input_str = self.input_field.toPlainText().strip()
# 初始化结果列表
segments = []
# 拆分字符串,保留 \( 和 \) 以及 \[ 和 \] 之间的内容和其他文本
while True:
# 找到 \( 和 \) 的位置
start_index_round = input_str.find(r'\(')
end_index_round = input_str.find(r'\)')
# 找到 \[ 和 \] 的位置
start_index_square = input_str.find(r'\[')
end_index_square = input_str.find(r'\]')
# 选择最先出现的起始标记
if start_index_round == -1 and start_index_square == -1:
break
elif start_index_round == -1 or (start_index_square != -1 and start_index_square < start_index_round):
start_index = start_index_square
end_index = end_index_square
delimiter_len = len(r'\[')
else:
start_index = start_index_round
end_index = end_index_round
delimiter_len = len(r'\(')
if end_index == -1:
break
# 添加起始标记前的文本
segments.append(input_str[:start_index])
# 添加标记之间的 LaTeX 片段
segments.append(input_str[start_index + delimiter_len:end_index])
# 更新 input_str
input_str = input_str[end_index + delimiter_len:]
# 添加剩余的文本(如果有)
if input_str:
segments.append(input_str)
str = ""
# 输出每个片段
for i, segment in enumerate(segments):
if self.contains_chinese_characters(segment):
str += (f"{segment.strip()}")
else:
if len(segment) < 20:
str += (f"${segment.strip()}$")
else:
str += (f"$${segment.strip()}$$")
self.text_display.setText(str)
def convert_to_latex(self):
input_str = self.input_field.toPlainText().strip()
# 初始化结果列表
segments = []
# 拆分字符串,保留 \( 和 \) 以及 \[ 和 \] 之间的内容和其他文本
while True:
# 找到 \( 和 \) 的位置
start_index_round = input_str.find(r'\(')
end_index_round = input_str.find(r'\)')
# 找到 \[ 和 \] 的位置
start_index_square = input_str.find(r'\[')
end_index_square = input_str.find(r'\]')
# 选择最先出现的起始标记
if start_index_round == -1 and start_index_square == -1:
break
elif start_index_round == -1 or (start_index_square != -1 and start_index_square < start_index_round):
start_index = start_index_square
end_index = end_index_square
delimiter_len = len(r'\[')
else:
start_index = start_index_round
end_index = end_index_round
delimiter_len = len(r'\(')
if end_index == -1:
break
# 添加起始标记前的文本
segments.append(input_str[:start_index])
# 添加标记之间的 LaTeX 片段
segments.append(input_str[start_index + delimiter_len:end_index])
# 更新 input_str
input_str = input_str[end_index + delimiter_len:]
# 添加剩余的文本(如果有)
if input_str:
segments.append(input_str)
str = ""
# 输出每个片段
for i, segment in enumerate(segments):
if self.contains_chinese_characters(segment):
str += (f"{segment.strip()}")
else:
if len(segment) < 20:
str += (f"{segment.strip()}")
else:
str += (f"{segment.strip()}")
self.text_display.setText(str)
def reset_input(self):
self.input_field.setText("请复制ChatGPT的公式粘贴在这里")
self.input_field.setStyleSheet("color: black;")
self.text_display.setText("转换后的信息将在这里展示")
self.text_display.setStyleSheet("color: black;")
def copy_to_clipboard(self):
clipboard = QApplication.clipboard()
clipboard.setText(self.text_display.toPlainText())
self.statusBar.showMessage("第五提示:复制成功!", 2000) # Show message for 2 seconds
if __name__ == "__main__":
app = QApplication(sys.argv)
window = FormulaConverterApp()
window.show()
sys.exit(app.exec_())
四、关于EXE运行程序
为了方便操作,我这里直接将代码打包成了exe可运行程序,找到客F回复“ZD004”领取就行,当然,若有其他问题也可以随时留言,我看到后一定第一时间回复。
(若没有找到可以直接搜店铺“第五设计”)