Как я могу захватить QKeySequence из QKeyEvent в зависимости от текущей раскладки клавиатуры?

Мне нужно сделать это для настройки моего приложения. У меня есть поле QLineEdit с переопределенным методом keyPressEvent.

QKeyEvent *ke = ...
QString txt;

if(ke->modifiers() & Qt::ControlModifier)
    txt += "Ctrl+";
if(ke->modifiers() & Qt::AltModifier)
    txt += "Alt+";
if(ke->modifiers() & Qt::ShiftModifier)
    txt += "Shift+";

if(ke->key() >= Qt::Key_0 && ke->key() <= Qt::Key_9)
    txt += ('0' + ke->key() - Qt::Key_0);
else if(ke->key() >= Qt::Key_A && ke->key() <= Qt::Key_Z)
    txt += ('A' + ke->key() - Qt::Key_A);
ui->hotkeyEdit->setText(txt);

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

Ответ 1

Что может оказаться очень полезным, так это функция QKeySequence().toString().

Ниже приведена часть кода, который я использую для захвата пользовательских ярлыков. С некоторыми изменениями он может делать все, что вам нужно в вашем проекте. Надеюсь, это поможет (извините за испорченную идентификацию):

if (event->type() == QEvent::KeyPress){ 
    QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event); 

    int keyInt = keyEvent->key(); 
    Qt::Key key = static_cast<Qt::Key>(keyInt); 
    if(key == Qt::Key_unknown){ 
        qDebug() << "Unknown key from a macro probably"; 
        return; 
    } 
    // the user have clicked just and only the special keys Ctrl, Shift, Alt, Meta. 
    if(key == Qt::Key_Control || 
        key == Qt::Key_Shift || 
        key == Qt::Key_Alt || 
        key == Qt::Key_Meta)
    { 
        qDebug() << "Single click of special key: Ctrl, Shift, Alt or Meta"; 
        qDebug() << "New KeySequence:" << QKeySequence(keyInt).toString(QKeySequence::NativeText); 
        return; 
    } 

    // check for a combination of user clicks 
    Qt::KeyboardModifiers modifiers = keyEvent->modifiers(); 
    QString keyText = keyEvent->text(); 
    // if the keyText is empty than it a special key like F1, F5, ... 
    qDebug() << "Pressed Key:" << keyText; 

    QList<Qt::Key> modifiersList; 
    if(modifiers & Qt::ShiftModifier) 
        keyInt += Qt::SHIFT; 
    if(modifiers & Qt::ControlModifier) 
        keyInt += Qt::CTRL; 
    if(modifiers & Qt::AltModifier) 
        keyInt += Qt::ALT; 
    if(modifiers & Qt::MetaModifier) 
        keyInt += Qt::META; 

    qDebug() << "New KeySequence:" << QKeySequence(keyInt).toString(QKeySequence::NativeText); 
}

Ответ 2

Если кто-то заботится о версии python решения Тихомира Долапчиева выше. Я просто перевел его, и он отлично работает. Просто отправьте для справки в будущем.

class KeySequenceEdit(QtGui.QLineEdit):
    """
    This class is mainly inspired by
    http://stackoverflow.com/a/6665017

    """

    def __init__(self, keySequence, *args):
        super(KeySequenceEdit, self).__init__(*args)

        self.keySequence = keySequence
        self.setKeySequence(keySequence)

    def setKeySequence(self, keySequence):
        self.keySequence = keySequence
        self.setText(self.keySequence.toString(QtGui.QKeySequence.NativeText))


    def keyPressEvent(self, e):
        if e.type() == QtCore.QEvent.KeyPress:
            key = e.key()

            if key == QtCore.Qt.Key_unknown:
                warnings.warn("Unknown key from a macro probably")
                return

            # the user have clicked just and only the special keys Ctrl, Shift, Alt, Meta.
            if(key == QtCore.Qt.Key_Control or
            key == QtCore.Qt.Key_Shift or
            key == QtCore.Qt.Key_Alt or
            key == QtCore.Qt.Key_Meta):
                print("Single click of special key: Ctrl, Shift, Alt or Meta")
                print("New KeySequence:", QtGui.QKeySequence(key).toString(QtGui.QKeySequence.NativeText))
                return

            # check for a combination of user clicks
            modifiers = e.modifiers()
            keyText = e.text()
            # if the keyText is empty than it a special key like F1, F5, ...
            print("Pressed Key:", keyText)

            if modifiers & QtCore.Qt.ShiftModifier:
                key += QtCore.Qt.SHIFT
            if modifiers & QtCore.Qt.ControlModifier:
                key += QtCore.Qt.CTRL
            if modifiers & QtCore.Qt.AltModifier:
                key += QtCore.Qt.ALT
            if modifiers & QtCore.Qt.MetaModifier:
                key += QtCore.Qt.META

            print("New KeySequence:", QtGui.QKeySequence(key).toString(QtGui.QKeySequence.NativeText))

            self.setKeySequence(QtGui.QKeySequence(key))

Ответ 3

Вы можете назначить сочетания клавиш для действий.

Вот как это сделать.

actionName->setShortcut(QKeySequence::New); //for predefined shortcuts like new, close, open..

или вы можете определить свой собственный ярлык с помощью этого

actionName->setShortcut(QKeySequence("Ctrl+N")); // sets Ctrl + N for w.e the action does

В первом случае qt автоматически определяет и назначает соответствующий ярлык для этого конкретного действия. Во втором случае вы можете выбрать свой собственный ярлык и набрать его как строку. Он автоматически анализирует и понимает.

Это позволяет избежать необходимости использования ключевых захватов для ненужных целей.

Ответ 4

Предпочитаете стандартную последовательность.

Из Проблемы с компоновкой клавиатуры:

В результате, как человекочитаемые строки, так и жестко закодированные коды клавиш могут быть проблематичными для использования при указании последовательности клавиш, которые могут использоваться на разных раскладках клавиатуры. Только использование стандартных ярлыков гарантирует, что пользователь сможет использовать ярлыки, которые разработчик предназначил.

Ответ 5

Самый простой способ:

if(event->type() == QEvent::KeyPress)
{
    QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
    qDebug() << "delete" << keyEvent->matches(QKeySequence::Delete);
    qDebug() << "copy" << keyEvent->matches(QKeySequence::Copy);
    qDebug() << "paste" << keyEvent->matches(QKeySequence::Paste);
}

Ответ 6

Попытка перехватить QKeySequence в keyPressEvent может работать не так, как ожидалось. И я нашел решение:

//  || event->type()== QEvent::ShortcutOverride is the key point
if (event->type() == QEvent::KeyPress || event->type()== QEvent::ShortcutOverride)
{
    QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
    if (keyEvent->matches(QKeySequence::Save))
    {
        // Do save
    }
}

Я надеюсь, что это помогает кому-то. :)

Ссылка: QWidget :: eventFilter() не перехватывает комбинации клавиш