6


1

Python / Tkinter:アラビア語/ヘブライ語のようなRTL(右から左)言語にTkinterを使用していますか?

Tkinterを使用して、アラビア語やヘブライ語などのRTL言語のユーザーインターフェイスをレンダリングすることは可能ですか? 私は「tkinter rtl」でグーグル検索を試みましたが、検索結果は期待外れでした。 Tk wikiは、現時点では双方向のサポートがないことを示しています。

アラビア語またはヘブライ語のロケール用にTkinterアプリケーションを開発している人はいますか?

3 Answer


3


これは古い質問ですが、昨日Tkinterと協力してPythonでヘブライ語のアプリケーションを開発し始めました。 右から左(bidi)はフレームワークの一部としては使用できませんが、少しグーグルで調べていくつかの調査を行った後、キーバインドと強制的にカーソルの位置を変更することで説得力を持って偽造しました。 My Entryウィジェットは左揃えを維持するため、ヘブライ語のテキストは同じボックスの英語とほぼ同じ位置にありますが、このアプローチは右揃えのボックスに簡単に変更できます。 (または、右揃えによりこれがより簡単になる場合があります)。 それにもかかわらず、ここに私がやったことがあります。

基本的に、ここで行うことは、コールバック、文字コード、およびインデックス定数を使用して手動でカーソル位置を強制することです。 また、矢印キーを考慮する必要があります(私はそれらが指す方向に移動するように振る舞います)。 私はいつもRTLが矢印を逆にする方法をいつも嫌っていました。 ただし、必要に応じて簡単に変更できます。)BackspaceとDelも、手動で再配置する必要があります。 もちろん、カーソルを手動で追跡している場合は、ユーザーがマウスを使用して位置を変更した場合に、追跡変数を更新する必要があります。 以下は私のコードです。ただし、ここでのグローバルの使用は、説明から複雑さを取り除くことを目的としています。

             # Here, the necessary bindings.  We're going to
             # have to make modifications on key press, release,
             # and on a completed mouse click.
             entryWidget.bind("", rtlPress)
             entryWidget.bind("", rtlRelease)
             entryWidget.bind("", rtlMouse)

次に、3つのコールバック関数は、すべてのカーソルの追跡と再配置を行います。

#With the following functions, keep in mind that we only want the cursor to move RIGHT
#(increase in index) in response to a right arrow press or a DEL.  Essentially, we are
#compensating for any movement but these explicit conditions.  Since the indexing of the
#cursor position is LTR, holding it in its current position
#while we append more text is
#tantamount to moving it right.

#On key release, if an arrow key has been invoked, we update our tracking variable to
#reflect the new cursor position.  If any other key was pressed, we snap the cursor back
#to where it was prior to the keypress to prevent it from moving right and cause the
#next letter to be appended on the left side of the previous letter.

def rtlRelease(event):
        global hebCursorPos
        if event.keycode==114 or event.keycode==113:
               hebCursorPos=event.widget.index(INSERT)
        else:
               event.widget.icursor(hebCursorPos)
        print(str(event.keycode)+" "+str(hebCursorPos))

#On keypress, we must compensate for the natural LTR behavior of backspace(22) and
#del(119)

def rtlPress(event):
        global hebCursorPos
        #In LTR text entry, a backspace naturally removes the character to the left of
        #the cursor.
        if event.keycode==22:
               length =  len(event.widget.get())
               #In RTL, the right edge is the beginning of the string, so backspace
               #should do nothing.
               #If we're at the right edge of the string, we insert a meaningless
               #character to be deleted so that it appears to the user as if we have
               #done nothing.
    if hebCursorPos==length:
                       event.widget.insert(hebCursorPos, " ")
               #In order to cause the backspace to delete the character to the right
               #rather than the left of the cursor from the user's perspective, we step
               #the cursor forward one.  This will cause the backspace to delete the
               #character to the left of the new cursor position, which will be the
               #character that was to the right of the cursor from the user's
               #perspective.  If we were at the right end of the line, we insert a space
               #and delete it milliseconds later.  We do not need to update the cursor's
               #position, in the tracking variable, because after the character is
               #deleted, it is back at the index from which it started, counting index
               #from an LTR perspective.
               event.widget.icursor(hebCursorPos+1)
        else:
               #Del is more of the same.  It deletes the character to the right of the
               #cursor, but we want it to delete the character to the right.
               if event.keycode==119:
               #If we're at the left edge of the string, insert a meaningless character
               #for the del to delete, so that from the user's perspective it does
               #nothing.
                        if hebCursorPos==0:
                               event.widget.insert(hebCursorPos, " ")
                        #Otherwise, we will be stepping the cursor one to the left, so
                        #that when it deletes the character to its new right, it will be
                        #deleting the character from what the user thinks is its left.
                        #Because we are deleting a character from the left of the cursor
                        #from the user's perspective, there will be fewer characters to
                        #the left of the cursor once the operation is complete.  As
                        #cursor positioning is tracked as an LTR index, we must update
                        #our tracking variable.
                        else:
                                hebCursorPos-=1
                #Now, we snap our cursor to the position of our tracking variable.
                #Either we are preventing it from drifting right due to overlapping
                #keypresses, or we are repositioning it to maintain the correct index
                #after a del.
                event.widget.icursor(hebCursorPos)

#Simply put, if the user repositions the cursor with the mouse, track it.
def rtlMouse(event):
         global hebCursorPos
         hebCursorPos=event.widget.index(INSERT)

お役に立てれば! 強制カーソルの動きによって達成されるため、入力中に視覚的なカーソルのジッターがわずかに発生しますが、テキストの順序は正しいように見え、ユーザーがキーを半押ししていない場合、カーソルは常に正しい位置を示します。 ただし、コードの完全性を主張しているわけではありません!


0


これで問題全体が解決されるわけではないかもしれませんが、主な問題であるディスプレイの問題を解決できる可能性があります。

基本的に、文字の順序を逆にするために2つのことが必要であり、それらを結合するには、このhttp://mpcabd.igeex.biz/python-arabic-text-reshaper/[reshaper]を使用しました。 الحركات`ですが、場合によってはまだバグがあります。


0


エントリまたはその他の要素を「jameel noori nastaleeq」またはその他のウルドゥー語フォントに設定してみてください