プログラマーに非常に人気のあるMarkdownエディターを知っておく必要があります。多くの人がMarkdownエディターを作成しています。クリエイティブな人もいれば、退屈な人もいます。
始める前に、tkinterを使用してMarkdownエディターを作成したくない理由を説明しましょう。これは、マークダウン入力HTMLデータを表示するデフォルトの単純なメソッドがないためです。HTMLデータを表示するデフォルトのtkinterコンポーネントすらありません。単にマークダウンを記述/編集できますが、アプリケーションで出力を表示する簡単な方法はありません。
ただし、これでtk_html_widgetsができたので、html出力の表示に役立ちます。
しかしもちろん、いくつかの問題もあります。フォントが小さすぎて、リモート写真の添付をサポートしていません。
それでは、構築を始めましょう。
構築を開始:
まず、Python 3とTkinterがインストールされていることを確認します。そうでない場合は、
python.org / downloads(TkinterはすでにPythonに含まれています)からダウンロードできます。
他に必要なものは、tkhtmlviewとmarkdown2です。それらをインストールするには、pip install tkhtmlview markdown2またはpip3 install tkhtmlview markdown2を実行します(複数のPythonバージョンがある場合)。
まず、必要なライブラリをインポートします。
from tkinter import *
from tkinter import font、filedialog
from markdown2 import Markdown
from tkhtmlview import HTMLLabel
最初の行では、tkinterパッケージから(ほとんど)すべてをインポートします。
2行目では、フォントとファイルのダイアログをインポートします。フォントを使用して入力フィールドのスタイル(フォント、フォントサイズなど)を設定し、ファイルダイアログをインポートして編集用のマークダウンファイルを開く(またはマークダウンファイルを保存する)必要があります。
3行目では、Markdownをインポートして、Markdownソースをhtmlに変換し、HTMLLabel(4行目でインポート)を使用して出力フィールドに表示します。
その後、Windowと呼ばれるフレームクラスを作成します。これは、スキンクラスのフレームクラスから継承します。入力フィールドと出力フィールドが保存されます。
クラス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 ()
このコードブロックでは、tkinterのフレームウィジェットクラスを継承するWindowというクラスを最初に定義します。
ここで、初期化関数で、マスターをパラメーターとして取り、それをフレームワークの親として使用します。次の行では、フレームを初期化します。
次に、self.myfontという名前のカスタムフォントオブジェクトを宣言します。このフォントファミリーはHelvetica(任意のフォントファミリーを選択できます)でサイズは15です。これは、マークダウン入力フィールドで使用されます。
最後に、init_window関数を呼び出して、アプリケーションをコアの場所に配置します。
fillキーワードパラメータをBOTHに設定します。これは、実際にはtkinterライブラリからインポートされます。フレームにウィンドウを水平方向と垂直方向の両方に塗りつぶすように指示し、expandキーワードパラメーターが1(Trueを意味する)に設定され、フレームが拡張可能であることを示します。つまり、ウィンドウサイズを拡大したり、ウィンドウサイズを最大化したりしても、フレームはウィンドウ全体に表示されます。
この問題を解決するために、スクリプトの最後に次のコードを追加します。
root = Tk()
root.geometry( "800x600")
app = Window(root)
app.mainloop()
次に、ウィンドウのジオメトリを800x600ボックスに設定します。800はウィンドウの高さ、600はウィンドウの幅です。次の行では、Windowオブジェクトを作成していることがわかります。ルート変数をフレームワークのルートにプッシュし、それをappという名前の変数に格納します。
次に行うことは、アプリケーションに実行を指示するmainloop関数を呼び出すことです!
しかし、これは単なる空白のウィンドウです。ウィンドウにコンテンツを書き込むには、マークダウンを書き込むテキストフィールドを追加する必要があります。これには、tkinterのテキストウィジェットを使用します。
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に増加します。スクリプトを実行して、すべてが正常かどうかを確認します。
さて、outputboxを追加する時が来たと思います。書くときにマークダウンソースコードのhtml出力が表示されます。
このためには、次のようにinit_window関数にHTMLLabelを追加する必要があります。
tkhtmlviewでHTMLLabelを使用していますが、幅は1のままです。ウィンドウが入力フィールドと出力ボックスの間で1:1の比率で共有されるため、幅を1に設定します(スクリプトを実行すると、意味がわかります)。
htmlキーワードパラメータには、初めて表示される値が格納されます。
次に、ウィンドウにパックし、入力フィールドの右側にRIGHTとしてサイドを置きます。fit_height()はテキストをウィジェットに合わせます。
次のようにコードを実行します。
これで、入力フィールドに書き込みを開始しても、入力しても出力は更新されません。これは、プログラムにこれを行うように指示していないためです。
これを行うには、まずイベントをエディターにバインドする必要があります。次に、テキストを変更すると、出力が次のように更新されます。
self.inputeditor.bind( "<< Modified >>"、self.onInputChange)
この行をinit_window()関数に入れます。
この行は、テキストが変更されたときにonInputChange関数を呼び出すようにinputeditorに指示します。しかし、その機能はまだないので、書き出す必要があります。
...
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オブジェクトを作成します。最後の行(上記の赤でマークされた行)は、最初に...待ちます!最後の行は、一部の読者を混乱させる可能性があります。3行に分けました。
markdownText = self.inputeditor.get( "1.0"、END)
html = md2html.convert(
markdownText )self.outputbox.set_html(html)
最初の行では、入力フィールドの上から下にマークダウンテキストを取得しています。最初のパラメーターself.inputeditor.getは、最初の行の0番目の文字(1.0 => [LINE_NUMBER]。[CHARACTER_NUMBER])からスキャンを開始するように指示し、最後のパラメーターは、最後に達するとスキャンを停止するよう指示します。
次に、md2html.convert()関数を使用して、スキャンしたマークダウンテキストをhtmlに変換し、html変数に格納します。
最後に、出力ボックスに.set_html()関数を使用して出力を表示するように指示します。
スクリプトを実行します。ほぼ通常の機能を備えたマークダウンエディタが表示されます。入力フィールドを入力すると、出力も更新されます。
しかし...私たちの仕事はまだ完了していません。ユーザーは少なくとも、テキストを開いて保存できる必要があります。
このため、メニューバーにファイルメニューを追加します。ここで、ユーザーはファイルを開いて保存したり、アプリケーションを終了したりできます。
init_window関数で、次の行を追加します。
self.mainmenu = Menu(self)
self.filemenu = Menu(self.mainmenu)
self.filemenu.add_command(label = "打开"、command = self.openfile)
self.filemenu.add_command(label = "另存是"、コマンド= 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クラスで2つの関数を定義する必要があります。この関数では、tkinterのファイルダイアログを使用します。
まず、ファイルを開く関数を定義しましょう。
def openfile(self):
openfilename = filedialog.askopenfilename(filetypes =(( "Markdown File"、 "* .md、* .mdown、* .markdown")、
( "Text File"、 "* .txt")、
( 「すべてのファイル」、「*。*」)))
openfilenameの場合:
try:
self.inputeditor.delete(1.0、END)
self.inputeditor.insert(END、open(openfilename).read())
以外:
print( "无法打开文件! ")
ここでは、最初にユーザーにファイルブラウザーダイアログを表示し、filedialog.askopenfilename()を使用して開くファイルを選択できるようにします。filetypesキーワード引数を使用して、サポートされているファイル(基本的にすべてのタイプのファイル)を含むタプルを渡すことにより、これらのタイプのファイルのみを開くようにダイアログボックスに指示します。
- 拡張子が.md、.mdown、.markdownのファイル、
- 拡張子が.txtのテキストファイル
- ワイルドカード拡張を使用する次の行では、拡張子が付いたファイルを開くようにダイアログボックスに指示しています。
次に、ユーザーがファイルを選択したかどうかを確認します。そうである場合、ファイルを開こうとします。次に、入力フィールドの最初の行の0番目の文字からフィールドの終わりまでのすべてのテキストを削除します。
次に、選択したファイルのコンテンツを開いて読み取り、コンテンツを入力フィールドに挿入します。
プログラムがファイルを開けない場合は、エラーが出力されます。しかし、これはエラーを処理するための良い方法ではありません。ここでできることは、次のようなエラーメッセージをユーザーに表示することです。
このためには、最初にメッセージボックスmessageboxをtkinterパッケージからインポートする必要があります。
tkinterからmboxとしてメッセージボックスをインポート
次に、上記のエラーメッセージを出力するだけでなく、その行を次の行に置き換えて、正しいエラーメッセージをユーザーに表示します。
mbox.showerror(「選択したファイルを開いているときにエラーが発生しました」、「エラー!選択したファイル:{}を開けませんでした!」。フォーマット(openfilename))
これにより、上記のファイルを開くことができない場合のスクリーンショットと同様に、エラーメッセージが作成されます。
mbox.showerror関数では、最初のパラメーターはメッセージボックスのタイトルです。2番目は、表示されるメッセージです。
次に、マークダウン入力を保存するsavefile関数を記述する必要があります。
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))
ここでは、最初に入力フィールドのすべての内容をスキャンし、変数に格納します。次に、2種類のファイルタイプ(.mdおよび.txt)を渡します。
ユーザーがファイル名を選択すると、変数filedataに格納されている入力フィールドの内容を保存しようとします。例外が発生すると、プログラムがファイルを保存できないことを示すエラーメッセージがユーザーに表示されます。
アプリケーションをテストしてバグをチェックすることを忘れないでください!プログラムにエラーがない場合は、次のように完全に実行されます。
はい、これです。あなたはそれを学びましたか?