首頁 >後端開發 >Python教學 >Python如何建構一個Markdown編輯器

Python如何建構一個Markdown編輯器

王林
王林轉載
2023-05-13 09:58:051526瀏覽

首先,請確保您已安裝Python 3和Tkinter。

我們需要的其他東西是tkhtmlview和markdown2。您可以透過執行pip install tkhtmlview markdown2或pip3 install tkhtmlview markdown2來安裝它們(如果您有多個Python版本)。

現在啟動您喜歡的編輯器或IDE並建立新檔案(例如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,Font Size),並匯入filedialog以開啟markdown檔案以進行編輯(和/或儲存我們的markdown檔案)。

在第三行中,導入了Markdown,以幫助我們將Markdown來源轉換為html,並使用HTMLLabel(在第四行中導入)將其顯示在輸出欄位中。

之後,我們將建立一個名為Window的框架類,該框架類別將從tkinters的Frame類別繼承。它將保存我們的輸入和輸出欄位。

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)

在此程式碼區塊中,我們先定義一個稱為Window的類,該類別繼承tkinter的Frame小工具類別。

現在,在初始化函數中,我們將master當作參數,當作框架的父級。在下一行中,我們初始化一個Frame。

接下來,我們宣告一個名為self.myfont的自訂字體對象,其字體家族為Helvetica(您可以選擇任何字體家族),大小為15,將在我們的markdown輸入欄位中使用。

最後,我們呼叫init_window函數,將我們的應用程式置於核心位置。

在init_window函數中,我們先將視窗的標題設定為linuxidc.com編輯器。在下一行self.pack(fill=BOTH, expand=1)中,我們告訴Frame佔用視窗的全部空間。

我們將fill關鍵字參數設為BOTH,這實際上是從tkinter庫匯入的。它告訴框架在水平和垂直方向上都填充窗口,並且expand關鍵字參數設置為1(表示True),這告訴我們框架是可擴展的。簡而言之,無論我們如何拉伸視窗大小或最大化視窗大小,框架都會填滿視窗。

現在,如果您正在執行www.linuxidc.com.py腳本,您將看不到任何內容,因為我們只定義了該類,但從未呼叫過它。

為了解決這個問題,我們將以下程式碼放在腳本的末尾:

root = Tk()  root.geometry("800x600")  app = Window(root)  app.mainloop()

接下來,將視窗的幾何形狀設定為800x600的長方體,800是視窗的高度,600是視窗的寬度。在下一行中,您可以看到我們正在建立一個Window物件。我們將root變數推入框架的root,並將其儲存在名為app的變數中。

接下來要做的就是呼叫mainloop函數,該函數告訴我們的應用程式運行!

現在運行www.linuxidc.com.py腳本。如果正確完成所有操作,您將看到一個空白窗口,如下所示:

Python如何建構一個Markdown編輯器

#但這只是一個空白視窗。要在視窗中寫入內容,我們需要新增一個文字字段,在其中寫入我們的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)

不要與...混淆(三個點),我把它們放在那裡只是為了表示在此程式碼區塊之前有多行程式碼。

在這裡,我們創建了一個寬度為1的Text小部件。不要誤會,以為錯了-這裡的大小是使用比例來完成的。當我們將其放入輸出框中時,您將在接下來的幾秒鐘內更清楚地了解它。

然後,我們將其包裝到框架中,並使其在水平和垂直方向上均可拉伸。

執行腳本時,您會看到已接管了整個「視窗」。如果您開始寫它,您可能會注意到字元太小了。

我已經知道會出現這個問題。這就是為什麼我之前告訴過您建立自訂字體物件(self.myfont)的原因。現在,如果您執行以下操作:

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

(這裡,我們告訴Text小工具使用自訂字體,而不是預設的小字體!)

...輸入欄位的字體大小將增加到15。執行腳本以檢查是否一切正常。

Python如何建構一個Markdown編輯器

現在,我認為是時候添加outputbox了,我們在編寫時將看到markdown原始碼的html輸出。

為此,我們要加入一個HTMLLabel,在init_window函數中是這樣的:

self.outputbox = HTMLLabel(self, width="1", background="white", html="<h2>linuxidc.com</h2>")  self.outputbox.pack(fill=BOTH, expand=1, side=RIGHT)  self.outputbox.fit_height()

我們使用tkhtmlview中的HTMLLabel,寬度仍舊為1。我們將寬度設為1,因為視窗將在輸入欄位和輸出框之間以1:1的比例共享(運行腳本時您會明白我的意思)。

html關鍵字參數儲存將在第一次顯示的值。

然后,将其打包在窗口中,将side作为RIGHT置于输入字段的右侧。fit_height()使文本适合小部件。

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

Python如何建構一個Markdown編輯器

现在,如果您开始在输入字段中书写,输入时输出不会得到更新。那是因为我们还没有告诉我们的程序这样做。

为此,我们首先要与编辑器绑定一个事件。然后,你进行修改文本,输出都会得到更新,如下所示:

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)重置修改后的标志,以便重用它。否则,在第一次事件调用之后,它将不再工作。

接下来,我们创建一个名为md2html的Markdown对象。最后一行(上面标红那行),首先我们…等等!最后一行可能会让一些读者感到困惑。我把它分成三行。

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,并将其存储在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)

简单说一下:

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

接下来,我们定义另一个菜单和上一个菜单作为其父菜单。它将作为我们的文件菜单。

然后使用add_command()和add_separator()函数添加3个子菜单(打开、另存为和退出)和分隔符。打开子菜单将执行openfile函数,另存为子菜单将执行savefile函数。最后,Exit将执行一个内建函数quit,该函数将关闭程序。

然后使用add_cascade()函数告诉第一个菜单对象包含filemenu变量。这包括标签文件中的所有子菜单。

最后,我们使用self.master.config()来告诉窗口使用主菜单作为窗口的菜单栏。

它看起来是这样的,但是现在还不要运行它。你会提示错误,openfile和savefile函数没有定义。

正如您现在看到的,我们必须在Window类中定义两个函数,我们将在其中使用tkinter的filedialog。

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

def openfile(self):      openfilename = filedialog.askopenfilename(filetypes=(("Markdown File", "*.md , *.mdown , *.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的文本文件

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

然后我们检查用户是否选择了一个文件。如果是,我们尝试打开文件。然后删除输入字段中从第一行的第0个字符到字段末尾的所有文本。

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

如果我们的程序不能打开一个文件,它将打印出错误。但是等等,这不是处理错误的好方法。我们在这里可以做的是向用户显示一个类似这样的错误消息:

Python如何建構一個Markdown編輯器

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

from tkinter import messagebox as mbox

然后,不像上面那样只是打印一个错误消息,我们将用下面的行替换那一行,以便向用户显示正确的错误消息。

mbox.showerror(“打开选定文件时出错 " , "哎呀!,您选择的文件:{}无法打开!".format(openfilename))

这将创建一个错误消息,就像我上面显示的文件无法打开时的屏幕截图一样。

mbox.showerror函数,第一个参数是消息框的标题。第二个是要显示的消息。

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

def savefile(self):          filedata = self.inputeditor.get("1.0" , END)          savefilename = filedialog.asksaveasfilename(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中的输入字段的内容。如果发生异常,我们将向用户显示一条错误消息,说明程序无法保存文件。

以上是Python如何建構一個Markdown編輯器的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除