如何在Gtk#TreeView中管理特殊用途的按键?

Bal*_*arq 12 c# treeview gtk# cell

我在Gtk#/ mono C#中有一个KeyPressed信号用于两个不同的目的,默认的TreeView中不存在:a)按TAB转到下一个单元格,b)按任意键开始编辑.

树视图是简单,它有一个ListStore仅示出的行和列,即,其保持表格数据.

我的代码如下.

[GLib.ConnectBefore]
protected void OnTableKeyPressed(object o, Gtk.KeyPressEventArgs args)
{
    int rowIndex;
    int colIndex;

    // Do not "eat" the key, by default
    args.RetVal = false;

    // Get the current position, needed in both cases.
    this.GetCurrentCell( out rowIndex, out colIndex );

    // Adapt the column
    colIndex += NumFixedColumns;

    if ( args.Event.Key != Gdk.Key.ISO_Enter ) {
        if ( args.Event.Key == Gdk.Key.Tab
          || args.Event.Key == Gdk.Key.ISO_Left_Tab )
        {
            if( args.Event.State == Gdk.ModifierType.ShiftMask ) {
                // Back
                colIndex -= 1;
                if ( colIndex < 1 ) {
                    colIndex = document.Columns;
                    --rowIndex;
                }

                rowIndex = Math.Max( 0, rowIndex );
            } else {
                // Advance
                colIndex += 1;
                if ( colIndex > document.Columns ) {
                    colIndex = 1;
                    ++rowIndex;
                }

                rowIndex = Math.Min( rowIndex, document.Rows );
            }

            this.SetCurrentCell( rowIndex, colIndex );
            args.RetVal = true;                              // Eat the TAB
        } else {
            this.SetCurrentCell( rowIndex, colIndex, true );
        }
    }

    return;
}
Run Code Online (Sandbox Code Playgroud)

我有两个问题:

  1. 如何向TreeView发信号通知单元格已完成编辑?问题是如果你没有编辑单元格时按TAB,一切正常.但是,如果用户正在编辑单元格,则到目前为止输入的内容将丢失.因此,如果用户正在编辑单元格,我想向TreeView发出信号以完成编辑,并继续使用当前行为.

  2. 如何在编辑单元格时避免丢失第一个键?说你在一个牢房.您按下键1,2,3和4.我的处理程序正确干扰,并将当前单元格置于编辑模式.但是,单元格只能获得2,3和4,但我设置arg.RetValfalse.

关于我的功能的信息

  • GetCurrentCell(row, col)将当前单元格从TreePath转换为一对整数.
  • SetCurrentCell(row, col, [edit])用于TreeView.SetCursor()使电池成为电流.edit假的.如果为true,则将单元格放入版本中.如果为,则不编辑任何内容.

azt*_*azt 3

我不是 GTK 方面的专家,事实上我从未使用过它。但我使用了标准控件来诱骗它们进行非默认行为。我特别修改了菜单栏,当按下 Alt 键时,菜单栏捕获所有输入,但我需要 Alt 键作为各种交互的修饰符。所以我可以为你提供一些关于欺骗你TreeView得到你需要的东西的一般性建议。

问题一:

根据您的描述,我认为默认行为是按Enter成功编辑,然后离开单元格取消编辑。这在许多应用中可能是可以接受的。其他软件(例如 Microsoft Excel)甚至在离开单元格时也倾向于接受编辑。所以我可以理解你想要这种行为。

如果没有这样的内置行为,您可以模拟用户必须执行的操作以发出TreeView完成编辑的信号,例如按 Enter。您可以使用此处描述的方法发送假的 Key 事件,或者如果 GTK 构建在 WPF 上(如此处。第二种方法更加底层,因为它确实将假按键事件植入到 Windows 事件队列中。我想这在任何情况下都应该有效,只要你的平台是 Windows。但我确信其他操作系统中也有类似的机制。

然后仅在此之后,转换到下一个单元格,TreeView获取失去焦点事件,但它不再处于编辑模式,并且不会发生任何事情。

问题2:

我认为发生的情况如下:按下一个键,TreeView但未处于编辑模式,因此忽略该事件。您获取事件并将其设置为编辑模式。但随后该事件将不会返回到TreeView,因此不再进行任何输入。

您可以尝试上述方法并手动重新发送按键事件。另一种方法是先捕获事件,然后再TreeView处理它。在 WPF 中经常存在该PreviewOn*事件(例如参见此处)。那么也许有这样的事件可供您控制?

你还可以把自己陷得更深。在 WPF 中,有一个InputManager.Current.PreProcessInput事件位于 Windows 消息循环之上,可让您过滤和处理各种输入。

这是我的代码片段,可能会对您有所帮助:

InputManager.Current.PreProcessInput += (sender, e) =>
{
    if (e.StagingItem.Input is MouseButtonEventArgs)
    {
        var earg = (MouseButtonEventArgs)e.StagingItem.Input;
        if (earg.RoutedEvent == Mouse.PreviewMouseDownOutsideCapturedElementEvent)
            OnPreviewMouseDownOutsideCapturedElement(sender, earg);
    }
};
Run Code Online (Sandbox Code Playgroud)

有关更多低级挂钩,请参阅例如此问题

祝你好运,如果您有更具体的问题,请发表评论。