【问题标题】:F# keyDown how to get the pressed keyF#keyDown 如何获取按下的键
【发布时间】:2015-05-29 11:03:14
【问题描述】:

在我当前的图形数独游戏项目中,我创建了一个按钮板,当您单击按钮时,它会被标记。标记按钮后,您应该能够按键盘上的数字,并且应该检索该数字(0..9)(如果按 0,则为 0,如果按 1,则为 1,依此类推)。

所以我的问题是:如何获取用户按下的键盘键,如果是数字则检索它,以便我可以将其放入二维数组并在标记按钮中显示为文本?

我包含了我的程序的一部分(如果你获得了 Fsharpx、System.Forms、System.Drawing 和其他必要的库,这很好编译),这样你就可以看到我到目前为止的想法。

namespace Sudoku
open FSharp.Control.Observable 

module Main =

    open System.Windows.Forms
    open System.Drawing

    let sudokuGame = Array2D.init 9 9 (fun x y -> 0)

    let form = new Form(Text="Sudoku game", TopMost=true, Width=360, Height=390)

    let buttonPos text x y = 
        let defaultSize = new Size(30,30) in
            (new Button(Text=text, Top=x, Left=y, Size=defaultSize, BackColor=Color.Aqua)) :> Control

    let gameButtons = [|for y in 1..9 do for x in 1..9 -> (buttonPos "0" (x*30) (y*30))|]

    let changeText pos c = (Array.get (gameButtons) (pos)).Text <- c

    form.Controls.AddRange gameButtons

    let rec obsMerger obsList =
            match obsList with
            | x1::[] -> x1
            | x1::xs -> Observable.merge x1 (obsMerger xs)
            | [] -> failwith "No Observables"

    let obsList = [for x in 81..(161) -> Observable.map(fun _ -> x) (gameButtons.[x-81].KeyDown)] @ [ for x in 0..80 ->  (Observable.map (fun _-> x) ((Array.get(gameButtons)(x)).Click)) ]

    let playModeObservables = obsMerger obsList 

    let rec playMode observable gameField lastPressed = async{

            let! somethingObservable = Async.AwaitObservable(observable) 

            match somethingObservable with
            | x     when x < 81 && x > -1  ->   return!  playMode observable gameField x
            | x     when x > 80 && x < 162 ->   changeText lastPressed ((x-80).ToString())
                                                return!  playMode observable gameField (x-81)
            | _                            ->   failwith "Shoot" 
        } 

    Async.StartImmediate(playMode playModeObservables sudokuGame 0) ; System.Windows.Forms.Application.Run(form)

【问题讨论】:

  • 使用他们的按键事件:msdn.microsoft.com/en-us/library/…
  • 我有一个可观察的监控 keyDown 事件,我显然可以得到它们,因为当我按下一个键时,我可以更改按钮中的内容。我遇到的主要问题是我似乎找不到(甚至在 msdn 中也找不到)如何获取按下了哪个键以及如何从该键确定用户插入了哪个值。
  • 您是否在链接页面上看到了 C# 示例,该代码很容易转换为 F#
  • 我尝试使用 c# 示例来使其正常工作,但到目前为止效果不佳。我想我知道 keyEventArgs 是如何工作的,但我看不到的是如何创建一个读取键盘并且可以通过例如“if e.KeyCode >= Keys.D0 || e.KeyCode
  • 您不会“创建”事件参数,它们会作为第二个参数传递给您的事件处理程序。

标签: forms button f# key sudoku


【解决方案1】:

感谢@johnpalmer,他向我展示了this 站点,并且因为this site 和@fyodorsoikin(他们指出了正确的方法)的一个例子,我能够解决这个问题。

要获取键,您需要一个 KeyEventHandler,它需要一个在按下键时将调用的函数。在此功能中,您可以检查其他内容并执行您需要执行的操作。

例如:

let stuffToDoWhenKeyPressed s (e : KeyEventArgs) = 
        match e with
        | e when e.KeyCode = Keys.D0 -> gameButtons.[0].Text <- "0"
        | e when e.KeyCode = Keys.D1 -> gameButtons.[0].Text <- "1" 
        | _  -> GUI.Play.gameButtons.[0].Text <- "?" 

gameButtons.[0].KeyDown.AddHandler(new System.Windows.Forms.KeyEventHandler (fun s e -> stuffToDoWhenKeyPressed s e ))

【讨论】:

  • 你可以简单一点:KeyDown.AddHandler(stuffToDoWhenKeyPressed) 和函数 stuffToDoWhenKeyPressed 可以改变 gameButtons.[0].Text on (s :?> Button).Text ....但是为什么只处理了 1 个按钮?
  • 啊,谢谢你试试看! :) 我这样做了,因为我刚刚学会了它应该如何完成,现在我将尝试使它适用于所有按钮。现在唯一的问题是如何使用按下的键值更新“通用按钮”中的文本。
  • 差不多这样:pastebin.com/aRw7yRaX我觉得这样的问题比较适合聊天:chat.stackoverflow.com/rooms/51909/f
猜你喜欢
  • 2021-06-12
  • 1970-01-01
  • 1970-01-01
  • 2012-04-18
  • 1970-01-01
  • 2016-03-28
  • 1970-01-01
  • 2014-09-23
  • 1970-01-01
相关资源
最近更新 更多