ホームページ  >  記事  >  バックエンド開発  >  Python で Markdown エディターを構築する方法

Python で Markdown エディターを構築する方法

王林
王林転載
2023-05-13 09:58:051464ブラウズ

まず、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 パッケージから (ほぼ) すべてのものをインポートします。

2 行目では、フォントとファイルのダイアログをインポートします。入力フィールド (フォント、フォント サイズなど) のスタイルを設定するためにフォントが必要であり、マークダウン ファイルを編集するために開く (および/またはマークダウン ファイルを保存する) ためにインポートされたファイル ダイアログが必要です。

3 行目では、Markdown ソースを HTML に変換し、HTMLLabel (4 行目でインポート) を使用して出力フィールドに表示できるように、Markdown がインポートされています。

その後、tkinters の Frame クラスを継承する Window というフレーム クラスを作成します。これは入力フィールドと出力フィールドを保持します。

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)

このコード ブロックでは、最初に、tkinter の Frame ウィジェット クラスを継承する Window というクラスを定義します。

ここで、初期化関数で、フレームの親として使用されるパラメーターとして master を渡します。次の行では、フレームを初期化します。

次に、マークダウン入力フィールドで使用される、フォント ファミリ Helvetica (任意のフォント ファミリを選択できます) とサイズ 15 を使用して、self.myfont という名前のカスタム フォント オブジェクトを宣言します。

最後に、init_window 関数を呼び出してアプリケーションを中心に置きます。

init_window 関数では、まずウィンドウのタイトルを linuxidc.com editor に設定します。次の行 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 はウィンドウの高さです。 window、600 はウィンドウの幅です。次の行では、Window オブジェクトを作成していることがわかります。ルート変数をフレームワークのルートにプッシュし、app という変数に保存します。

次に行うことは、アプリケーションの実行を指示する mainloop 関数を呼び出すことです。

ここで、www.linuxidc.com.py スクリプトを実行します。すべてを正しく実行すると、次のような空のウィンドウが表示されます。

Python で 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)

(3 つのドット) と混同しないでください。このコード ブロックの前に複数のコード行があることを示すために、これらを配置しています。

ここでは、幅 1 のテキスト ウィジェットを作成します。誤解しないでください。ここでのサイズ設定は比率を使用して行われます。それを出力ボックスに入れると、次の数秒でよりよく理解できるようになります。

それをフレームに包み、縦横に伸縮できるようにします。

スクリプトを実行すると、「ウィンドウ」全体が引き継がれていることがわかります。書き始めると文字が小さいことに気づくかもしれません。

この問題が発生することはすでにわかっていました。これが、前にカスタム フォント オブジェクト (self.myfont) を作成するように言った理由です。ここで、次の操作を実行するとします。

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

(ここでは、デフォルトの小さいフォントの代わりにカスタム フォントを使用するようにテキスト ウィジェットに指示します!)

...のフォント サイズ入力フィールドは 15 に増加します。スクリプトを実行して、すべてが正常かどうかを確認します。

Python で Markdown エディターを構築する方法

ここで、出力ボックスを追加すると思います。作成中にマークダウン ソース コードの HTML 出力が表示されます。

これを行うには、init_window 関数で次のような HTMLLabel を追加する必要があります。

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 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。