Advertisement

python在线编辑器搭建_使用Python构建属于自己的Markdown编辑器

阅读量:

python.org/downloads(Tkinter已包含Python中)。

另外所需的工具包括tkhtmlview以及markdown2。您可以通过安装tkhtmlview以及markdown2的方式使用这些工具;另外一种方式是通过pip3安装tkhtmlview以及markdown2。(如果有多个Python版本)

现在请开启您个人偏好的编程工具或集成开发环境,并创建一个新的项目文件夹(例如:www.linuxidc.com.py,请您将其命名为linuxidc.com编辑器)。

我们将从导入必要的库开始。

from tkinter import *

from tkinter import font , filedialog

from markdown2 import Markdown

from tkhtmlview import HTMLLabel

在第一行中,我们从tkinter包中导入(几乎)所有内容。

在第二行部分中, 我们引入了字体元素以及文件管理界面. 通过设置输入字段样式(如Font Font Size), 同时导入filedialog以便打开及编辑markdown文档(以及可能地将其保存).

在第三行中,我们引入了Markdown技术;通过该技术, 我们能够将Markdown源文档转换为HTML格式。其中, 在第四行我们又引入了HTMLLabel组件, 并将其配置到输出字段中。

随后

class Window(Frame):

def init(self, master=None):

Frame.init(self, master)

self.master = master

self.myfont = font.Font(family="Helvetica", size=14)

self.init_window

def init_window(self):

self.master.title("linuxidc.com编辑器")

self.pack(fill=BOTH, expand=1)

在此代码块内

现在,在初始化函数中,我们将master作为参数,并将其用作框架的父类。在下一行中创建了一个Frame

接下来,在我们的Markdown编辑器中定义一个名为self.myfont的定制字体对象。该字体将被设定为其家族属性值为Helvetica(建议选择其他常见字体家族以获得不同风格),大小设置为15px,并将用于我们的markdown输入字段。

最后,我们调用init_window函数,将我们的应用程序置于核心位置。

在init_window函数的第一行,在第一行我们给窗口起名为linuxidc.com编辑器。在接下来的一行中使用self.pack(fill=BOTH, expand=1),告诉Frame占据整个窗口区域。

我们将fill关键字参数赋值为BOTH。这是从tkinter库导入的关键字。该指示着框架在水平与垂直方向上填充窗口。此外,在设置expand关键字参数为1(即True)时,则表明该框架是可以扩展的。The Bottom Line is that no matter how we adjust the window size or maximize it, the framework will fill the window accordingly.

当前, 如果有人运行www.linuxidc.com.py脚本, 他们不会有任何输出, 因为我们的类中未进行相关内容的实现, 并且从未被调用。

为了解决这个问题,我们将以下代码放在脚本的末尾:

root = Tk

root.geometry("800x600")

app = Window(root)

app.mainloop

接下来,请将窗口设定为宽×高的矩形区域(Width × Height),其中,默认宽度设为933像素,默认高度设为544像素)。 在下一行中,请注意以下代码块的位置以及与之相关的注释位置(注:此处应使用代码块标记)。\n\n\n请确保所有代码块均正确无误地嵌入到主程序逻辑之中。\n\n\n请注意,在某些情况下,默认参数可能会影响最终结果。\n\n\n此外,在某些情况下,默认参数可能会影响最终结果。\n\n\n此外,在某些情况下,默认参数可能会影响最终结果。\n\n\n此外,在某些情况下,默认参数可能会影响最终结果。\n\n

接下来要做的就是调用mainloop函数,该函数告诉我们的应用程序运行!

为了实现这一目标,请启动该特定Python脚本文件...。(注:数学公式需保留原样)

3feaf0c856044c86b9e9f2c5c2781209.jpg

然而这只是一块空窗体。为了在该窗体中输入内容 我们应在此窗体中嵌入一个Text控件 在此控件上编写我们的Markdown标记语言。为此 我们将调用tkinter库中的Text类构造函数来创建并配置这个文本编辑区域。

...

def init_window(self):

self.master.title("linuxidc.com编辑器")

self.pack(fill=BOTH, expand=1)

self.inputeditor = Text(self, width="1")

self.inputeditor.pack(fill=BOTH, expand=1, side=LEFT)

避免将...视为误解项(三个逗号),为了表明在该代码块前面有若干行代码。

我们生成了一个Text组件,并将其尺寸设置为1。请注意这个细节,请不要误以为这里存在什么问题-这里的大小设定实际上是基于比例计算得出的结果。当我们将这个组件放置到输出区域时,在接下来的几秒钟内您将能够更直观地理解其功能和作用机制。

然后,我们将其包装到框架中,并使其在水平和垂直方向上均可拉伸。

运行脚本时,请注意整个界面已被成功接管。请确保在启动该脚本时注意字体大小设置。

5f7830c0dbb247fd94f01a368353a7d1.jpeg

我已经认识到可能会出现这个问题。这也是我之前告知您创建自定义字体对象(self.myfont)的原因。现在,请您按照以下步骤操作:

self.inputeditor = Text(self, width="1" , font=self.myfont)

(这里,我们告诉Text小部件使用自定义字体,而不是默认的小字体!)

...输入字段的字体大小将增加到15。运行脚本以检查是否一切正常。

b630592dd9b94d2cafefda735cc4be71.jpeg

目前我意识到到了添加一个outputbox的时间已经成熟,并且在编写过程中你将能够观察到markdown源代码被转换为html的过程。

为此,我们要添加一个HTMLLabel,在init_window函数中是这样的:

self.outputbox = HTMLLabel(self, width="1", background="white", html="

linuxidc.com

")

self.outputbox.pack(fill=BOTH, expand=1, side=RIGHT)

self.outputbox.fit_height

我们设置了HTMLLabel的宽度为1,并将其固定在视图中以确保显示效果的一致性。

html关键字参数存储将在第一次显示的值。

然后,在窗口内放置该组件;将side设置为RIGHT并将其放置于输入字段的右侧。通过fit_height调整使其适应文本内容

现在运行代码,如下所示:

8a52a38164624cdaa37d9c5516313fa3.jpeg

当您开始在输入字段中书写时

为了解决问题

self.inputeditor.bind("<>", self.onInputChange)

将这一行放到init_window函数中。

这一行指示inputeditor在文本发生更改时触发onInputChange函数。然而我们目前还未实现该功能,请将其编码完成。

...

def onInputChange(self , event):

self.inputeditor.edit_modified(0)

md2html = Markdown

self.outputbox.set_html(md2html.convert(self.inputeditor.get("1.0" , END)))

在第一行处, 我们调用edit_modified(0)来重新设置标记的值. 如果不进行相应的操作, 在第一次事件触发后该标记将无法被正确读取.

随后

markdownText = self.inputeditor.get("1.0" , END)

html = md2html.convert(markdownText)

self.outputbox.set_html(html)

在第一行中, 我们从输入字段顶端到底端提取了markdown文本. 第一个参数通过self.inputeditor.get获取信息, 并指示从第0个字符开始扫描 (1.0对应[LINE_NUMBER].[CHARACTER_NUMBER]). 最后一个参数设置为停止扫描的位置.

随后, 我们调用md2html.convert函数来解析扫描得到的markdown文本, 并将其生成为html格式, 并将其存储到指定变量中。

最后,我们告诉outputbox使用.set_html函数来显示输出!

执行该脚本。您将看到一个接近正常功能的markdown编辑器。当在输入字段中输入时,请注意输出相应地被更新。

但是…我们的工作还没有完成。用户至少需要能够打开和保存他们的文本。

为此我们需要将一个文件菜单添加到菜单栏中 在该菜单中用户可以选择打开或保存文件 并可让用户退出程序

在init_window函数中,我们将添加以下行:

self.mainmenu = Menu(self)

self.filemenu = Menu(self.mainmenu)

self.filemenu.add_command(label="打开", command=self.openfile)

self.filemenu.add_command(label="另存为", command=self.savefile)

self.filemenu.add_separator

self.filemenu.add_command(label="退出", command=self.quit)

self.mainmenu.add_cascade(label="文件", menu=self.filemenu)

self.master.config(menu=self.mainmenu)

简单说一下:

在这里,我们定义了一个新菜单,框架作为它的父菜单。

接下来我们将命名为新结构的另一个现有菜单以及上一个现有菜单作为其父结构。该系统将以此为基础创建文件导航

通过创建一个包含三个子菜单(启动、保存文件和退出)以及分隔符的组件来扩展功能。 启动子菜单将启动openfile函数, 保存文件子菜单将执行savefile函数. 最终, 退出程序将通过调用内建quit函数实现, 该函数负责关闭程序.

接着, 我们通过调用add_cascade函数向第一个菜单对象传达包含有filemenu变量的信息. 该操作会涵盖所有嵌入在标签文件中的子菜单选项.

最后一步操作中, 我们使用self.master.config来设置window的菜单栏为master menu

02da77377b784193b56e9b84053c1ae3.jpeg

它的外观目前还未完成,并不应立即运行。程序会报错,并且openfilesavefile函数尚未被定义

它的外观目前还未完成,并不应立即运行。程序会报错,并且openfilesavefile函数尚未被定义

就目前的情况而言,在Window类中我们需要定义两个函数,并且这些函数将利用tkinter模块提供的文件对话框。

首先让我们定义打开文件的函数:

def openfile(self):

selectedFileName = file open dialog.get the path of, specifying text document format with extensions .md, .mdown, and .markdown.

("Text File", "*.txt"),

("All Files", ".")))

if openfilename:

try:

self.inputeditor.delete(1.0, END)

self.inputeditor.insert(END , open(openfilename).read)

except:

print("无法打开文件!")

在这里,在这一位置上向用户展示一个窗口界面,并允许他们通过filedialog.askopenfilename方法来选择想要打开的文件。结合使用filetypes关键字参数以及传递一个包含所需支持文件类型的元组(几乎涵盖了所有可能的类型),我们可以设置对话框参数以实现特定的选择逻辑:其中第一个元素对应于支持的第一个扩展名...]

带 .md , .mdown , .markdown扩展名的文件,

扩展名为.txt的文本文件

在使用通配符扩展的下一行中,我们告诉对话框打开任何扩展名的文件。

带 .md , .mdown , .markdown扩展名的文件,

扩展名为.txt的文本文件

在使用通配符扩展的下一行中,我们告诉对话框打开任何扩展名的文件。

随后我们核查用户是否选择了文件如果存在则尝试打开该文件接着在输入字段中删除从第一行的第一个字符开始一直到字段末端的所有内容

接下来,我们打开并读取所选文件的内容,并在输入字段中插入内容。

如果无法打开文件,则会显示错误信息。然而,并非最佳解决方案。我们可以采取的做法是向用户展示类似这样的错误提示。

0318927fe6c449969b88c5a30609faea.jpeg

为此,我们首先要从tkinter包中导入消息框messagebox。

from tkinter import messagebox as mbox

然后,在这种情况下仅仅显示一个错误信息可能还不够。

mbox.showerror(“无法在打开指定文件时读取” , “请检查您选择的文件路径是否正确!” .format(openfilename))

此操作将生成一个错误提示信息:类似于我在上文中展示的文件无法打开时的画面捕捉。

在Python tkinter模块中,showerror函数的第一个参数用于指定消息框的标题字段;第二个参数则用于指定要显示的信息字段。

现在,我们需要编写一个savefile函数来保存markdown输入。

def savefile(self):

filedata = self.inputeditor.get("1.0" , END)

savesavefilename = filedialog.ask_saveas_filename(filetypes=((("Markdown File", "*.md"))))

("Text File", "*.txt")) , title="保存 Markdown 文件")

if savefilename:

try:

f = open(savefilename , "w")

f.write(filedata)

except:

mbox.showerror("保存文件错误" , "哎呀!, 文件: {} 保存错误!".format(savefilename))

在当前环境中,在处理过程中我们首先遍历输入字段中的所有数据项并将其保存到一个变量中。接下来为两种文件类型(.md和.txt)

当用户选定一个文件名时, 系统会尝试将位于变量filedata中的输入字段的数据内容进行持久化存储操作。在遇到错误时, 请注意查看提示信息, 并告知无法将数据持久化存储

请确保您对应用程序进行测试,并检查是否存在任何bug!如果您的程序运行无误,则运行结果应当是理想的:

7f3a519bdff54bdcbe6d19f6e17c8011.jpeg

OK,本文就这样,你学会了吗?

了解更多关于Python的相关信息,请访问Python 专题页面https://www.linuxidc.com(topicnews.aspx?tid=17)

Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx

全部评论 (0)

还没有任何评论哟~