如何使用 Cairo 在 drawingArea 小部件上绘图?

How do I draw on drawingArea widget using Cairo?

我有这个小项目,我尝试使用 gi-gtk 在 window 上绘图。

https://github.com/bigos/cairo-example/blob/b9480dc63d6fff3bc195d35c7422f193fc8ae7d4/src/Main.hs

我已经弄清楚如何让 gi-gtk 与 Cairo 一起工作了。

https://github.com/haskell-gi/haskell-gi/wiki/Using-Cairo-with-haskell-gi-generated-bindings

但是我在获取 cairo 上下文时遇到了问题。在下面的代码中,我有两个事件。第一个事件工作正常。但是当我听到 window 对象上的按键时,我无法弄清楚如何获得在 canves 上绘图所需的 cairo 上下文。

  win <- Gtk.windowNew WindowTypeToplevel
  canvas <- Gtk.drawingAreaNew
  Gtk.containerAdd win canvas

  _ <- Gtk.onWidgetDraw canvas $ \context ->
    renderWithContext context (updateCanvas canvas) >> pure True

  _ <- Gtk.onWidgetKeyPressEvent win $ \x -> do
    vvv <- Gdk.getEventKeyKeyval x
    -- How do I draw on canvas here?
    (putStrLn ("You have pressed key code " ++  (show vvv))) >> pure True

简单地说,你不能。您将无法访问 onWidgetDraw 回调之外的绘图上下文。

您可以(并且应该)做的是使用全局状态来允许您的 onWidgetDraw 回调根据发生的情况绘制不同的东西。例如,如果你想在用户按下向右箭头时绘制一些文本:

  • onWidgetKeyPressEvent 回调中,在用户按下所选键时在全局状态中设置一个值
  • onWidgetDraw 回调中,使用该值来确定是否必须绘制文本。

    理想情况下,您会尝试使您的状态适合 State Monad 或类似的东西 - 但是,在这种特定情况下,Gtk 不允许注入 Monadic 状态本身,因此这不是直接可能的。您必须求助于 IORefs、TVars 或任何等价物。

    祝你好运! :)