fltk-rs 事件
这一章讨论了FLTK事件模型以及如何在您的程序或 widget 中处理事件。
FLTK Event 模型
每当用户移动鼠标、点击一个按钮或按下一个键时,都会生成一个事件并发送给您的 app 。事件也可以来自其他程序,如窗口管理器。
通过传递整数参数给handle()方法(重写Fl_Widget::handle()的虚拟方法)来识别事件。关于最近事件的其他信息存储在静态位置,可以通过调用Fl::event_*()方法获得。这些静态信息在从窗口系统读取下一个事件之前都是有效的,因此在handle()方法之外查看它们是可以的。
事件编号可以使用fl_eventnames[]数组(在#include <FL/names.h>中定义)转换为它们的实际名称,具体细节请参见下一章。
在下一章中,MyClass::handle()示例展示了如何重写 Fl_Widget::handle() 方法来接受和处理特定事件。
Mouse Events
FL_PUSH
鼠标点击一个按钮。您可以通过调用Fl::event_button()来查看是哪个按钮。您可以通过调用Fl::event_x()和Fl::event_y()来得到鼠标位置。
widget 通过从其handle()方法返回非零值来表示它“想要”鼠标点击,如MyClass::handle()示例所示。然后它将成为Fl::pushed() widget ,并将获得FL_DRAG和匹配的FL_RELEASE事件。如果handle()返回零,则FLTK将尝试将FL_PUSH发送给另一个 widget 。
FL_DRAG
鼠标在按住按钮的情况下移动。当前按钮状态在Fl::event_state()中得到。鼠标位置在Fl::event_x()和Fl::event_y()中得到。
为了接收FL_DRAG事件, widget 在处理FL_PUSH时必须返回非零值。
FL_RELEASE
鼠标按钮点击已释放。您可以通过调用Fl::event_button()来查看是哪个按钮。
为了接收FL_RELEASE事件, widget 在处理FL_PUSH时必须返回非零值。
FL_MOVE
鼠标在没有按住任何按钮的情况下移动。此事件发送给Fl::belowmouse() widget 。
为了接收FL_MOVE事件, widget 在处理FL_ENTER时必须返回非零值。
FL_MOUSEWHEEL
用户已滑动鼠标滚轮。Fl::event_dx()和Fl::event_dy()方法可用于找到水平和垂直滚动的量。
Focus Events
FL_ENTER
鼠标光标已移动到 widget 区域内。这可以用于突出显示反馈。如果 widget 想要突出显示或以其他方式跟踪鼠标,它应通过从其handle()方法返回非零值来表示这一点。然后它将成为Fl::belowmouse() widget ,并将接收FL_MOVE和FL_LEAVE事件。
FL_LEAVE
鼠标已从 widget 区域内移出。
为了接收FL_LEAVE事件, widget 在处理FL_ENTER时必须返回非零值。
FL_FOCUS
这表示试图给 widget 键盘 focus。
如果 widget 想要 focus,它应该改变自己以显示它拥有 focus 的事实,并从其handle()方法返回非零值。然后它将成为Fl::focus() widget ,并获得FL_KEYDOWN、FL_KEYUP和FL_UNFOCUS事件。
focus 改变,要么因为窗口管理器改变了哪个窗口获得 focus ,要么因为用户尝试使用Tab键、箭头键或其他键进行导航。您可以使用Fl::event_key()来确定它为什么移动。对于导航,它将是按下的键,对于与窗口管理器的交互,它将是零。
FL_UNFOCUS
当另一个 widget 获得 focus 或窗口失去 focus 时,此事件将发送给之前的Fl::focus() widget 。
Keyboard Events
FL_KEYBOARD, FL_KEYDOWN, FL_KEYUP
一个键已按下(FL_KEYDOWN)或释放(FL_KEYUP)。FL_KEYBOARD是FL_KEYDOWN的同义词,在本文档中两个名称可以互换使用。
键可以在Fl::event_key()中找到。键应插入的文本可以在Fl::event_text()中找到,其长度在Fl::event_length()中。
如果您使用了键,则handle()应返回1。如果返回零,则FLTK假设您忽略了键,并将尝试将其发送给父 widget 。如果他们都不想要它,它将把事件变成FL_SHORTCUT事件。FL_KEYBOARD事件也由 character palette/map 生成。
要接收FL_KEYBOARD事件,您还必须通过返回1来响应FL_FOCUS和FL_UNFOCUS事件。这样FLTK才知道是否要发送键盘事件给您的 widget 。(有些 widget 不需要它们,例如Fl_Box。)
如果您正在编写文本编辑 widget,您可能还需要调用 Fl::compose() 函数将单个击键转换为字符。
FL_KEYUP事件发送给当前具有 focus 的 widget 。这不一定是接收相应FL_KEYDOWN事件的同一个 widget ,因为 focus 可能在事件之间发生了变化。
FL_SHORTCUT
在Fl::focus() widget 为零或忽略FL_KEYBOARD事件的情况下,FLTK尝试将此事件发送给它能发送的每个 widget ,直到其中一个返回非零值。FL_SHORTCUT首先发送给Fl::belowmouse() widget ,然后是其父母和兄弟姐妹,最终发送给窗口中的每个 widget ,试图找到一个返回非零值的对象。[18][18]FLTK非常努力地不忽略任何按键!
您还可以通过使用Fl::add_handler()来制作“全局”快捷键。全局快捷键无论显示哪个窗口或哪个窗口具有 focus 都有效。
此 widget 不再活动,因为在其上或其父母上调用了deactivate()。请注意,尽管在接收此事件后此 widget 的active()可能仍返回true,但只有在它和所有父母的active()都为true时,它才真正活动。(您可以使用active_r()来检查这一点)。[19][19]
此 widget 现在活动,因为在其上或其父母上调用了activate()。
此 widget 不再可见,因为在其上或其父母上调用了hide(),或者由于父窗口被最小化。请注意,尽管在接收此事件后此 widget 的visible()可能仍返回true,但只有在它和所有父母的visible()都为true时,它才真正可见。[20][20](您可以使用visible_r()来检查这一点)。[21][21]
此 widget 再次可见,因为在其上或其父母上调用了show(),或者由于父窗口被恢复。子Fl_Window将通过实际创建窗口(如果尚未完成)来响应此事件,因此如果您对窗口进行子类化,请确保将FL_SHOW传递给基类handle()方法!
本章中的事件(“ widget 事件”),即FL_ACTIVATE、FL_DEACTIVATE、FL_SHOW和FL_HIDE,是停用和不可见 widget 通常可以获得的唯一事件,具体取决于它们的状态。在某些情况下,也可能会将FL_LEAVE或FL_UNFOCUS事件发送给停用或隐藏的 widget 。[22][22]
在您调用Fl::paste()后的某个时间,您应该获得此事件。Fl::event_text()的内容是要插入的文本,字符数在Fl::event_length()中。
Fl::selection_owner()将在选择移动到另一个 widget 之前获得此事件。这表明某个其他 widget 或程序已声称选择。Motif程序使用此功能来清除选择指
Drag and Drop Events
- UTF-8编码传输:FLTK支持从桌面任何 app 拖放文本和文件到FLTK widget ,使用UTF-8编码传输文本。
- 文件接收格式:文件以完整路径和文件名列表形式接收,用换行符分隔。
- 特定平台处理:在某些X11平台上,文件以URL编码的UTF-8字符串接收,非ASCII字节(和空格、%等)被替换为"%XY"形式,其中XY是字节的十六进制值。
- 拖放数据获取:拖放数据在FL_PASTE事件结束时通过Fl::event_text()获取。在某些平台上,FL_DND_*事件也可获取事件文本,但 app 不应依赖此行为,因为它取决于每个平台使用的协议。
- FL_DND_*事件限制:FL_DND_*事件不能在从Fl_Group或Fl_Window派生的 widget 中使用。[1][1]
FL_DND_ENTER
鼠标移动到指向 widget 时,若 widget 希望接收拖放数据,必须返回1以接收FL_DND_DRAG、FL_DND_LEAVE和FL_DND_RELEASE事件。[2][2]
FL_DND_DRAG
鼠标在拖动数据时移动到 widget 内部, widget 应指示可能的放置位置。
FL_DND_LEAVE
鼠标移出 widget 。
FL_DND_RELEASE
用户释放鼠标按钮,将数据放入 widget 。如果 widget 返回1,它将在紧接着的FL_PASTE事件中接收数据。
其他 Events
FL_SCREEN_CONFIGURATION_CHANGED
每当屏幕配置发生变化(添加/移除屏幕、屏幕分辨率变化、屏幕移动)时发送。使用Fl::add_handler()来获得此事件通知。[3][3]
FL_FULLSCREEN
app 窗口从普通模式变为全屏,或从全屏变为普通模式。如果使用支持扩展窗口管理器提示的X窗口管理器,此事件将在变化实际发生后才会传递。
Fl::event_*()方法
FLTK将最近事件的信息保存在静态存储中。这些信息在下一个事件处理之前都是有效的。因此,它在handle()和callback()方法内部是有效的。[4][4]
这些都是非常简单的内联函数,因此非常快速且占用空间小。
Fl::event_button()
Fl::event_clicks()
Fl::event_dx()
Fl::event_dy()
Fl::event_inside()
Fl::event_is_click()
Fl::event_key()
Fl::event_length()
Fl::event_state()
Fl::event_text()
Fl::event_x()
Fl::event_x_root()
Fl::event_y()
Fl::event_y_root()
Fl::get_key()
Fl::get_mouse()
Fl::test_shortcut()

浙公网安备 33010602011771号