我正在尝试设计一个带有用户自定义热键的 Qt GUI 应用程序。我遇到的主要问题是如何在应用程序中同步热键,因为多个小部件/组件可能会使用特定的热键(例如,复制)。
我目前的策略是使用一个引用类,该类包含每个不同热键的 QKeySequence 对象列表。每个小部件都必须有一种方法来引用这个主列表,并具有低级 keyPressEvent 的自定义实现,它将比较输入的键与热键。不过,我不是特别喜欢这种策略,因为它需要在每个小部件中进行大量的重新实现,感觉就像我在重新发明轮子。
我还尝试使用 QAction 对象,它可以在内部保存 QKeySequence 快捷方式,然后使用这些来触发我可以使用插槽和信号处理的更高级别的事件。但是,我在这里遇到的主要问题是如何管理将信号路由到哪些插槽。
例如,假设我有 2 个打开的小部件,它们都可以接收 copy 操作信号。我可以将这两个的插槽连接到相同的信号,并利用快捷方式的单个更新点,但随后事情变得困惑,因为只有事件小部件应该对复制信号起作用,而不是两个小部件。我可以重新实现 focusOutEvent 和 focusInEvent 处理程序来手动连接/断开插槽,但这似乎也遇到了上面我试图重新连接的相同问题发明轮子,做不必要的工作。
有没有更简单的方法解决这个问题?
最佳答案
我认为这个问题没有特别简单/简单的解决方案,但是当我需要向我的应用程序添加用户可自定义的热键时,我是这样做的:
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 创建代码运行之前,只需确保 key 设置文件存在于磁盘上。这是我程序的键映射文件的摘录(我将其存储为一个简单的 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,就不能“即时”修改键绑定(bind)(至少,在没有大量额外编码的情况下是这样)。我的程序通过在用户单击“编辑键绑定(bind)”对话框中的“保存并应用”后关闭然后重新创建所有窗口来解决这个问题。
5) 一个可选的进一步步骤(这是一些额外的前期工作,但从长远来看可以节省时间)是编写一个程序(或脚本)来查找程序代码库中的所有 .cpp 文件以查找调用 GetKeySequence( ) 在代码中。当它找到 GetKeySequence() 调用时,它会解析调用的两个参数,并使用默认设置将它们作为一行打印在键绑定(bind)文件中。这很有用,因为您可以将此脚本作为自动构建的一部分,此后无论何时向您的菜单添加新菜单项(或其他键序列说明符),您都不必记住手动更新默认键设置文件程序。
无论如何,这对我来说效果很好。优点是您根本不必重构现有程序;您可以根据需要通过插入 GetKeySequence() 来完成它,同时保持程序的更大逻辑/结构不变。
关于c++ - Qt 用户自定义热键,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13435262/
我正在尝试设置一个puppet节点,但rubygems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由rubygems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby
我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby1.9+ 关于ruby-主要:Objectwhenrun
我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano
我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c