【问题标题】:How do I draw on drawingArea widget using Cairo?如何使用 Cairo 在drawingArea 小部件上绘图?
【发布时间】:2018-05-05 18:04:29
【问题描述】:

我有一个小项目,我尝试使用 gi-gtk 在窗口上绘图。

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 上下文时遇到了问题。在下面的代码中,我有两个事件。第一个事件工作正常。但是当我听到窗口对象上的按键时,我无法弄清楚如何获得在画布上绘制所需的 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

【问题讨论】:

  • 我已经有一段时间没有编写 gtk 了。可能你只能从onWidgetDraw drwa,而你在小部件上使用Gtk.widgetQueueDraw 来触发绘图。这是有道理的,因为 UI 总是必须能够重绘窗口,所以无论你在 onWidgetKeyPressEvent 中绘制什么,如果可以的话,当用户调整窗口大小时都会丢失。

标签: haskell gtk cairo


【解决方案1】:

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

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

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

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

    祝你好运! :)

【讨论】:

  • 我不是说你错了,但我发现了以下函数可能会为你的答案添加一些东西hackage.haskell.org/package/gi-gtk-3.0.22/docs/…hackage.haskell.org/package/gi-gtk-3.0.22/docs/…
  • 只有在我暴露或调整窗口大小时才会触发绘图事件。我需要弄清楚如何在按键上触发绘图事件
  • 在我的按键事件中,我可以说 Gtk.widgetQueueDraw 画布并强制调用小部件的重绘。不是我需要弄清楚全局状态。
  • Documentation for C 请注意user_data 可以是指向任何地方的指针,您可以在其中存储不同的值
  • +1。这是对的。 queue_draw(或Gtk.widgetQueueDraw)也是正确的使用方法。我不熟悉 Haskell,但在其他语言中,典型的解决方案可能是使用全局变量来处理状态。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多