我认为这个问题没有特别简单/不乏味的解决方案,但是当我需要向我的应用程序添加用户可自定义的热键时,我是这样做的:
1) 从具有硬编码快捷键的应用程序开始,例如这样的代码:
QMenu * editMenu = new QMenu;
QAction * copyItem = menu->addAction(tr("Copy"), this, SLOT(CopyData()));
copyItem->setShortcut(tr("Ctrl+C"));
2) 创建一个如下所示的 GetKeySequence() 函数:
static QHash<QString, QKeySequence> _usersKeyPreferences;
static bool _usersKeyPreferencesLoaded = false;
QKeySequence GetKeySequence(const QString & keySequence, const QString & contextStr)
{
if (_usersKeyPreferencesLoaded == false)
{
// Oops, time to load in the user's saved custom-key settings from a file somewhere
_usersKeyPreferences = LoadUsersKeyPreferencesFromFile();
_usersKeyPreferencesLoaded = true; // so we'll only try to load the file once
}
if (_usersKeyPreferences.contains(contextStr))
{
return _usersKeyPreferences[contextStr];
}
else
{
// No user preference specified? Okay, fall back to using the
// hard-coded default key sequence instead.
return QKeySequence(qApp->translate(contextStr, keySequence));
}
}
3) 现在是乏味的部分:对所有代码以及任何你明确指定键序列的地方(如步骤 1 所示代码的第三行),用调用 GetKeySequence() 来包装它,像这样:
copyItem->setShortcut(GetKeySequence(tr("Ctrl+C"), tr("Edit_Menu|Copy")));
4)此时,您的程序的键序列将是可定制的;只需确保在 GUI 创建代码运行之前磁盘上存在密钥设置文件即可。这是我程序的键映射文件(我将其存储为简单的 ASCII 文本文件)的摘录:
Edit_Menu|Copy = Ctrl+C
Edit_Menu|Cut = Ctrl+X
Edit_Menu|Paste = Ctrl+V
[... and so on for all other menu items, etc...]
...当然,这种方法的一个缺点是,一旦创建了 GUI,就不能“即时”修改键绑定(至少,在没有大量额外编码的情况下)。我的程序只需在用户单击“编辑键绑定”对话框中的“保存并应用”后关闭并重新创建所有窗口即可解决此问题。
5) 一个可选的进一步步骤(这是一些额外的工作,但从长远来看可以节省时间)是编写一个程序(或脚本),对程序代码库中的所有 .cpp 文件进行 greps 查找调用 GetKeySequence()代码。当它找到 GetKeySequence() 调用时,它会解析出调用的两个参数,并将它们打印为具有默认设置的键绑定文件中的一行。这很有用,因为您可以将此脚本作为自动构建的一部分,此后您将永远不必记住在向您添加新菜单项(或其他键序列说明符)时手动更新默认键设置文件程序。
无论如何,这对我来说效果很好。优点是您根本不必重构现有程序;您可以根据需要插入 GetKeySequence() ,同时保持程序的更大逻辑/结构完好无损。