如何使用箭头键更改小部件之间的焦点?

Posted

技术标签:

【中文标题】如何使用箭头键更改小部件之间的焦点?【英文标题】:How to change focus between widgets using arrow keys? 【发布时间】:2014-03-17 07:10:26 【问题描述】:

我正在 FLTK 中处理 UI,我的基本问题归结为:

我在主窗口上有一堆小部件(输入、输出、按钮小部件)。比如说,16 个项目(4 行 x 4 列)。我需要使用箭头键在小部件之间导航。

主要是,如果焦点在 (r4, c4)(右下角小部件)上:

按右箭头应将焦点转移到 (r1, c1)(左上角小部件)。 按左箭头应将焦点转移到(r4,c3)。 向上箭头按下应将焦点转移到 (r3, c4)。 向下箭头按下应将焦点转移到 (r1, c4)。

即根据我们的习惯,导航应该非常直观地工作。

默认情况下,使用箭头(或 Tab)键时,小部件之间的焦点会按照它们的创建顺序进行更改。向上和向右总是转到下一个小部件(按创建顺序),向下和向左总是转到上一个小部件(按创建顺序)。

有没有办法在 FLTK 中做到这一点? 还是我需要创建一个算法来做到这一点?

【问题讨论】:

【参考方案1】:

查看分发测试程序中名为 demo.cxx 的程序。它似乎无需任何特殊编程即可完成您想要的操作。

    首先关注退出按钮。 当您按 Tab 时,焦点会变为按钮框组 如果您随后开始使用箭头键,焦点会按照您预期的方式改变。

如果您需要,这里是一个示例

#include <FL/FL.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Button.H>
#include <string>
#include <vector>

int ROWS = 4;
int COLS = 4;
int BUTTON_WID = 40;
int BUTTON_HGT = 40;
int BUTTON_SEP = 5;

// These must exist for the duration otherwise
// we get a load of random text as labels
std::vector<std::string> buttonLab;

Fl_Window* CreateGrid()

    int gridwid = (BUTTON_WID + BUTTON_SEP) * COLS + BUTTON_SEP;
    int gridhgt = (BUTTON_HGT + BUTTON_SEP) * ROWS + BUTTON_SEP;
    Fl_Window* grid = new Fl_Window(gridwid, gridhgt, "GridTest");
    grid->begin();

    // Create the labels first - if the vector reallocates
    // the fltk widgets lose the pointers
    char tag[] = "@";
    for (int rr = 0; rr < ROWS; ++rr)
    
        for (int cc = 0; cc < COLS; ++cc)
        
            ++tag[0];
            buttonLab.push_back(tag);
        
    

    // Create the buttons
    int ix = -1;
    for (int ypos = BUTTON_SEP; ypos < gridhgt; ypos += (BUTTON_HGT + BUTTON_SEP))
    
        for (int xpos = BUTTON_SEP; xpos < gridwid; xpos += (BUTTON_WID + BUTTON_SEP))
        
            Fl_Button* button = new Fl_Button(xpos, ypos, BUTTON_WID, BUTTON_HGT, buttonLab[++ix].c_str());
        
    
    grid->end();
    return grid;


int main(int argc, char* argv[])

    Fl_Window* grid = CreateGrid();
    grid->show(argc, argv);
    Fl::run();
    return 0;

编辑: 如果小部件是按随机顺序创建的,覆盖导航的最简单方法是提供您自己的 Fl_Group::navigation 函数。这可以通过

    使 Fl_Group::navigation 虚拟化并重建 FLTK。然后基于 Fl_Group 创建一个新的组类并覆盖导航功能。 优点:每当更新包时,它都会有所有的 FLTK 更新。 缺点:有人必须记住在获得新的 FLTK 时将 Fl_Group::navigation 设为虚拟。 复制 Fl_Group.c 和 Fl_Group.h 并将它们重命名为新的组类。重写导航功能。 优点:无需重新构建 FLTK。 缺点:更新FLTK时不会更新Fl_Group。

将您所有的小部件放在这个新的组类中,您将控制导航

【讨论】:

尽管在 demo.cxx 和您的代码中,我们都能够根据要求正确导航,但他们这样做主要是因为小部件的 创建顺序 是这样的FLTKs 能够正确分配导航顺序。 您创建小部件的顺序是什么。 我的问题是这样的,考虑到:-我特别不按顺序创建小部件。我可以随意地在说 (r1, c1) 之前创建 (r4, c4) 等等。 - 一些小部件可能完全不存在。例如。 (r3, c3) 可能根本不存在 主要是这需要我非常频繁地不断添加和删除小部件,并且有大量的小部件(创建相当随意)。因此,不可能跟踪它们的创建顺序等。为了简单起见,我举了一个 4x4 的例子。 所有的小部件都是同一类型吗?如果是,您可以先创建它们,然后更改标签。【参考方案2】:

你想要的例程是 Fl_Widget->take_focus()

【讨论】:

以上是关于如何使用箭头键更改小部件之间的焦点?的主要内容,如果未能解决你的问题,请参考以下文章

如何配置 QTreeView 以在使用箭头键移动时保留多项选择

防止在 Flash AS2 事件处理程序中使用箭头键更改焦点?

如何获取具有焦点的小部件

如何从Tkinter,Python中的Text小部件中移除焦点

如何在 FLTK 中对两个不同的小部件同时使用键盘箭头和鼠标单击?

[使用箭头键的WPF数据网格单元格循环