Python / Tkinter: использование Tkinter для языков RTL (справа налево), таких как арабский / иврит?

Можно ли использовать Tkinter для рендеринга пользовательских интерфейсов для языков RTL, таких как арабский или иврит? Я попробовал поискать в Google на "tkinter rtl", и результаты поиска разочаровали. Tk wiki указывает, что в настоящее время поддержка двунаправленного текста отсутствует.

Кто-нибудь разрабатывает приложения Tkinter для арабского языка или иврита?


person Malcolm    schedule 10.11.2010    source источник
comment
подробнее об этом: wiki.tcl.tk/699   -  person noob oddy    schedule 22.07.2011
comment
Примерно с 2011 года tk и, следовательно, tkinter и IDLE поддерживают двунаправленный иврит и арабский язык в Windows, используя поддержку Windows. wiki.tcl.tk/3158. Я просто добавил некоторые из них в образец выбора шрифта на IDLE, чтобы люди могли видеть, что работает, а что нет в их конкретной системе.   -  person Terry Jan Reedy    schedule 13.11.2017


Ответы (3)


Я понимаю, что это старый вопрос, но я только вчера начал работать с Tkinter, чтобы разработать приложение на иврите на Python. Направление справа налево (биди) недоступно как часть фреймворка, но после небольшого поиска в Google и некоторых исследований мне удалось убедительно подделать его с помощью сочетаний клавиш и принудительного изменения положения курсора. Виджет My Entry сохраняет выравнивание по левому краю, поэтому текст на иврите находится примерно в том же положении, что и английский в том же блоке, но этот подход можно легко изменить для блока, выровненного по правому краю. (Или это может упростить выравнивание по правому краю). Тем не менее, вот что я сделал.

По сути, вы здесь вручную устанавливаете положение курсора с помощью обратных вызовов, кодов символов и индексных констант. Кроме того, вы должны учитывать клавиши со стрелками (мои ведут себя как движущиеся в том направлении, на которое они указывают. Я всегда ненавидел, как RTL обычно переворачивает стрелки. Однако это легко изменить, если вы предпочитаете иное). Backspace и Del, Кроме того, придется вручную изменить положение. Конечно, если вы отслеживаете курсор вручную, вам необходимо обновить переменную отслеживания в том случае, если пользователь перемещает ее с помощью мыши. Ниже мой код, за исключением того, что использование здесь global предназначено для того, чтобы убрать часть сложности из объяснения.

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

Затем три функции обратного вызова, которые выполняют все отслеживание и перемещение курсора.

#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)

Надеюсь это поможет! Поскольку это выполняется принудительным движением курсора, во время набора наблюдается небольшое визуальное дрожание курсора, но порядок текста кажется правильным, и курсор, кажется, всегда указывает правильную позицию, когда пользователь не нажимает среднюю клавишу. Однако я не претендую на совершенство кода!

person JPittard    schedule 23.10.2011
comment
Это ужасный взлом, и он решает лишь часть проблем, связанных с отображением текста на арабском / иврите. - person dietr; 05.04.2012

Возможно, это тоже не решает всей проблемы, но может решить проблему отображения, в которой я вижу основную проблему.

в основном вам понадобятся две вещи, чтобы изменить порядок символов и позволить им объединиться, я использовал этот преобразователь он отлично работал с простыми словами без диакритических знаков الحركات, но в некоторых случаях все равно не работал.

person Hady Elsahar    schedule 29.07.2014

Попробуйте установить для ввода или другого элемента значение «jameel noori nastaleeq» или любой другой шрифт урду.

person yasin ullah    schedule 13.01.2019