Qt用户可自定义的热键

hel*_*922 5 c++ qt qt4

我正在尝试使用用户可自定义的热键设计Qt GUI应用程序.我遇到的主要问题是如何在应用程序中同步热键,因为多个小部件/组件可能使用特定的热键(例如,副本).

我目前的策略是使用一个引用类,它包含QKeySequence每个不同热键的对象列表.每个小部件都必须有一种方法来引用这个主列表并具有低级别的自定义实现keyPressEvent,它将比较输入的密钥和热键.不过,我并不特别喜欢这种策略,因为它需要在每个小部件中进行重大改造,并且感觉我正在尝试重新发明轮子.

我还尝试使用QAction可以在QKeySequence内部保存快捷方式的对象,然后使用这些对象来触发我可以使用插槽和信号处理的更高级别的事件.但是,我在这里遇到的主要问题是如何管理哪些插槽信号被路由到.

例如,假设我有2个打开的小部件,它们都可以接收copy动作信号.我可以将这两个插槽连接到同一个信号,并利用快捷方式的单个更新点,但事情变得混乱,因为只有活动小部件应该作用于复制信号,而不是两个小部件.我可以重新实现focusOutEventfocusInEvent处理程序来手动连接/断开插槽,但这也似乎遇到了上面我正在尝试重新发明轮子并做更多工作而不是必要的问题.

有没有更容易解决这个问题的方法?

Jer*_*ner 6

我不认为这个问题有一个特别简单/非繁琐的解决方案,但是当我需要在我的应用程序中添加用户可自定义的热键时,我就是这样做的:

1)从具有硬编码密钥快捷方式的应用程序开始,例如:

QMenu * editMenu = new QMenu;
QAction * copyItem = menu->addAction(tr("Copy"), this, SLOT(CopyData()));
copyItem->setShortcut(tr("Ctrl+C"));
Run Code Online (Sandbox Code Playgroud)

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));
   }
}
Run Code Online (Sandbox Code Playgroud)

3)现在这个单调乏味的部分:对所有代码进行深入研究,以及明确指定键序列的任何地方(如步骤1中显示的代码的第三行),通过调用GetKeySequence()包装它,像这样:

copyItem->setShortcut(GetKeySequence(tr("Ctrl+C"), tr("Edit_Menu|Copy")));
Run Code Online (Sandbox Code Playgroud)

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...]
Run Code Online (Sandbox Code Playgroud)

......当然,这种方法的一个缺点是,一旦创建了GUI,就无法"动态"修改密钥绑定(至少,没有大量额外的编码).我的程序只需通过关闭然后在用户单击"编辑键绑定"对话框中的"保存并应用"后重新创建所有窗口来解决此问题.

5)一个可选的进一步步骤(预先进行一些额外的工作,但从长远来看节省时间)是编写一个程序(或脚本),它会覆盖程序代码库中的所有.cpp文件,以查找调用中的GetKeySequence()码.当它找到GetKeySequence()调用时,它会解析出调用的两个参数,并使用默认设置将它们作为一行打印在一个键绑定文件中.这很有用,因为您可以将此脚本作为autobuild的一部分,然后每当您向其添加新的菜单项(或其他键序列说明符)时,您都不必记得手动更新默认的键设置文件.程序.

无论如何,这对我来说效果很好.优点是您根本不必重构现有程序; 您可以根据需要插入GetKeySequence(),同时保持程序的较大逻辑/结构不变.