How to insert accented characters into text entries in PyQt5?

My text entries in PyQt5 (QLineEdit, QPlainTextEdit, Dialogs,...) do not accept accented characters typed on the keyboard. I can only enter them if I type them into another editor and appeal to Crtl+C, Crtl+V, or by commands in the source code. This happens the text widgets, no matter if they were created locally, dynamically, or imported from Qt Designer. I believe the problem is in PyQt, because when I test in Qt Designer, they work perfectly. I use Ubuntu Studio. Does anyone know how to solve?

Author: David Jesse, 2017-03-29

1 answers

I managed to solve. At least, for me, it works. I did the following:

From QLineEdit, QPlainTextEdit, and QTextEdit, I created three new widgets, respectively, QLineEdit_Ac, QPlainTextEdit_Ac, and QTextEdit_Ac.

If interested, to use these widgets just add the file acentos.py and import them. If you decide to test the code, leave your feedback in the comments that help. You can also help develop them.

Acentos.py

# -*- coding: utf-8 -*-
from PyQt5.QtWidgets import QTextEdit, QLineEdit, QPlainTextEdit

class acentuacao():
    """
    KEYS : código das teclas "text_widget.before_key" que acionarão a substituição: (til, acento circunflexo, acento agudo, crase, trema)
    CA : cada CA[i] corresponde ao seu KEY[i] --> devem estar na mesma ordem
    cada um dos itens de cada CA[i] é representado como
    ('~', ('a', 'e', 'i, ...),('ã', 'ẽ', 'ĩ',...)) onde:
        '~' : caracter que deve ser impresso, caso o seguinte não esteja na relação, 
        ('a', 'e', 'i, ...) : caracteres que serão substituidos
        ('ã', 'ẽ', 'ĩ',...) : caracteres que pelos quais, respectivamente, aqueles serão substituidos
    """
    KEYS = [16781907, 16781906, 16781905, 16781904, 16781911]
    CA = [
         ('~', ('a', 'e', 'i', 'o', 'u', 'n', 'A', 'E', 'I', 'O', 'U', 'N'),
               ('ã', 'ẽ', 'ĩ', 'õ', 'ũ', 'ñ', 'Ã', 'Ẽ', 'Ĩ', 'Õ', 'Ũ', 'Ñ')),
         ('^', ('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'),
               ('â', 'ê', 'î', 'ô', 'û', 'Â', 'Ê', 'Î', 'Ô', 'Û')),
         ('',  ('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'),
               ('á', 'é', 'í', 'ó', 'ú', 'Á', 'É', 'Í', 'Ó', 'Ú')),
         ('`', ('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'),
               ('à', 'è', 'ì', 'ò', 'ù', 'À', 'È', 'Ì', 'Ò', 'Ù')),
         ('',  ('a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'),
               ('ä', 'ë', 'ï', 'ö', 'ü', 'Ä', 'Ë', 'Ï', 'Ö', 'Ü')) ]

    def check_acentuacao(text_widget, event):
        Result = None
        if text_widget.before_key in acentuacao.KEYS:
            n = acentuacao.KEYS.index(text_widget.before_key)
            ca = acentuacao.CA[n]
            r = ca[0]                               # inicializando, apenas com o sinal
            if str(event.text()) in ca[1]:          # se event.text() é um dos caraceres substituíveis,
                i = ca[1].index(str(event.text()))
                r = ca[2][i]                        # r assume o valor deste, com seu respectivo acento
            Result = r

        if not event.key() == 16777248:    # O Shift é uma tecla problemática, porque muda o codigo do before_key
            text_widget.before_key = event.key()

        """ Para visualizar o valor de cada tecla (KEY) pessionada, descomente a linha abaixo """
        #print('KEY =',  event.key())

        return Result

#***************************************************************************************************
#************* QLineEdit  ******************************************************************************
class QLineEdit_Ac(QLineEdit):
   def __init__(self, parent=None):
      super(QLineEdit_Ac, self).__init__(parent)
      QLineEdit_Ac.before_key = None

   def keyPressEvent(self, e):
       Rt = acentuacao.check_acentuacao(QLineEdit_Ac, e)
       if Rt != None:
           self.insert(Rt)
       else:
           super(QLineEdit_Ac, self).keyPressEvent(e)

#***********  QTextEdit_Ac ************************************************************************
class QPlainTextEdit_Ac(QPlainTextEdit):
    def __init__(self, parent=None):
        super(QPlainTextEdit_Ac, self).__init__(parent)
        QPlainTextEdit_Ac.before_key = None

    def keyPressEvent(self, e):
        Rt = acentuacao.check_acentuacao(QTextEdit_Ac, e)
        if Rt != None:
            self.insertPlainText(Rt)
        else:
            super(QPlainTextEdit_Ac, self).keyPressEvent(e)

#***********  QTextEdit_Ac ************************************************************************
class QTextEdit_Ac(QTextEdit):
    def __init__(self, parent=None):
        super(QTextEdit_Ac, self).__init__(parent)
        QTextEdit.before_key = None

    def keyPressEvent(self, e):
        Rt = acentuacao.check_acentuacao(QTextEdit_Ac, e)
        if Rt != None:
            self.insertPlainText(Rt)
        else:
            super(QTextEdit_Ac, self).keyPressEvent(e)

Teste.py

# -*- coding: utf-8 -*-
""" Serve para testar, e exemplo de uso dos widgets 
    QLineEdit_Ac, QPlainTextEdit_Ac e QTextEdit_Ac
"""
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from acentos import *

class Exemplo(QMainWindow):
    def __init__(self):
        super().__init__()
        # Criando os Widgets de entrada de texto acentuado
        unica_linha = QLineEdit_Ac()
        multi_linhas = QPlainTextEdit_Ac()
        rich_text = QTextEdit_Ac()
        # ---A partir daqui, nenhuma novidade...
        self.setWindowTitle('Teste de acentuação')
        frame = QFrame()
        self.setCentralWidget(frame)

        layout = QVBoxLayout()
        layout.addWidget(QLabel('Única Linha (QLineEdit_Ac)'))
        layout.addWidget(unica_linha)
        layout.addWidget(QLabel('Várias linhas (QPlainTextEdit_Ac)'))
        layout.addWidget(multi_linhas)
        layout.addWidget(QLabel('Editor Rich Text (QTextEdit_Ac)'))
        rich_text.insertHtml("<b><big>Até</big></b> isso <small>é</small> "
                             "<font color = blue><i> possível!</i></font>")
        layout.addWidget(rich_text)
        frame.setLayout(layout)
        self.statusBar()

        # Menus
        exitAct = QAction(QIcon('exit.png'), '&Sair', self)
        exitAct.setShortcut('Ctrl+Q')
        exitAct.setStatusTip('Vazar beco afora...')
        exitAct.triggered.connect(qApp.quit)

        aboutAct = QAction("Sobre o App...", self)
        aboutAct.setStatusTip('Sobre este app...')

        aboutQtAct = QAction("Sobre Qt...", self)
        aboutQtAct.setStatusTip('Sobre a biblioteca Qt em uso...')

        aboutAct.triggered.connect(self.about)
        aboutQtAct.triggered.connect(QApplication.instance().aboutQt)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&Arquivo')
        fileMenu.addAction(exitAct)

        helpMenu = self.menuBar().addMenu("Sobre...")
        helpMenu.addAction(aboutAct)
        helpMenu.addAction(aboutQtAct)


        # Centrar o App na tela
        App_Width = 500
        App_Height = 400

        screen_resolution = app.desktop().screenGeometry()

        posx = int((screen_resolution.width() - App_Width) / 2 )
        posy = int((screen_resolution.height() - App_Height) / 2 )
        self.setGeometry(posx, posy, App_Width, App_Height)

        self.show()

    def about(self):
        QMessageBox.about(self, "Sobre este app",
            "Esta é uma demonstração do uso do QLineEdit_Ac e "
            "QTextEdit_Ac, widgets estes, que, respectivamente possibilitam o "
            "uso da acentuação no QLineEdit e QTextEdit. "
            "Caso encontre algum bug, por favor, comunique.\n"
            "David Jesse")


if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = Exemplo()
    sys.exit(app.exec_())
 0
Author: David Jesse, 2017-04-02 04:12:04