【问题标题】:How to handle Quit command (Cmd-Q) in Mac OS X in Haskell gtk2hs如何在 Haskell gtk2hs 中处理 Mac OS X 中的退出命令(Cmd-Q)
【发布时间】:2016-05-22 04:28:32
【问题描述】:

我正在https://github.com/gtk2hs/gtk2hs/blob/master/gtk/demo/hello/World.hs 试用示例程序,转载如下:

-- A simple program to demonstrate Gtk2Hs.
module Main (Main.main) where

import Graphics.UI.Gtk

main :: IO ()
main = do
  initGUI
  -- Create a new window
  window <- windowNew
  -- Here we connect the "destroy" event to a signal handler.
  -- This event occurs when we call widgetDestroy on the window
  -- or if the user closes the window.
  on window objectDestroy mainQuit
  -- Sets the border width and tile of the window. Note that border width
  -- attribute is in 'Container' from which 'Window' is derived.
  set window [ containerBorderWidth := 10, windowTitle := "Hello World" ]
  -- Creates a new button with the label "Hello World".
  button <- buttonNew
  set button [ buttonLabel := "Hello World" ]
  -- When the button receives the "clicked" signal, it will call the
  -- function given as the second argument.
  on button buttonActivated (putStrLn "Hello World")
  -- Gtk+ allows several callbacks for the same event.
  -- This one will cause the window to be destroyed by calling
  -- widgetDestroy. The callbacks are called in the sequence they were added.
  on button buttonActivated $ do
    putStrLn "A \"clicked\"-handler to say \"destroy\""
    widgetDestroy window
  -- Insert the hello-world button into the window.
  set window [ containerChild := button ]
  -- The final step is to display this newly created widget. Note that this
  -- also allocates the right amount of space to the windows and the button.
  widgetShowAll window
  -- All Gtk+ applications must have a main loop. Control ends here
  -- and waits for an event to occur (like a key press or mouse event).
  -- This function returns if the program should finish.
  mainGUI

如果我在 Mac OS X 上构建并运行它,Cmd-Q 或应用程序菜单中的退出命令不会关闭应用程序。如何捕获此事件并使其关闭应用程序?

更新

我在我的项目中添加了一个 gtk3-mac-integration 依赖项,在我的源文件中添加了一个 import Graphics.UI.Gtk.OSX 以及在调用 initGUI 之后立即添加以下内容:

app <- applicationNew
on app willTerminate (return ())

我肯定错过了一些东西,因为这似乎没有任何作用(请参阅https://github.com/rcook/gtkapp/commit/8531509d0648ddb657633a33773c09bc5a576014)。

更新编号。 2

感谢@Jack Henahan 和OSXDemo.hs,我现在有了一个可行的解决方案:

-- A simple program to demonstrate Gtk2Hs.
module Main (Main.main) where

import Control.Exception
import Control.Monad
import Graphics.UI.Gtk
import Graphics.UI.Gtk.OSX

showDialog :: Window -> String -> String -> IO ()
showDialog window title message = bracket
    (messageDialogNew (Just window) [] MessageInfo ButtonsOk message)
    widgetDestroy
    (\d -> do
        set d [ windowTitle := title ]
        void $ dialogRun d)

main :: IO ()
main = do
    void initGUI

    -- Create a new window
    window <- windowNew

    -- Here we connect the "destroy" event to a signal handler.
    -- This event occurs when we call widgetDestroy on the window
    -- or if the user closes the window.
    void $ on window objectDestroy mainQuit

    -- Sets the border width and tile of the window. Note that border width
    -- attribute is in 'Container' from which 'Window' is derived.
    set window [ containerBorderWidth := 10, windowTitle := "Hello World" ]

    -- Creates a new button with the label "Hello World".
    button <- buttonNew
    set button [ buttonLabel := "Hello World" ]

    -- When the button receives the "clicked" signal, it will call the
    -- function given as the second argument.
    void $ on button buttonActivated (putStrLn "Hello World")

    void $ on button buttonActivated $ showDialog window "THE-TITLE" "THE-MESSAGE"

    -- Gtk+ allows several callbacks for the same event.
    -- This one will cause the window to be destroyed by calling
    -- widgetDestroy. The callbacks are called in the sequence they were added.
    void $ on button buttonActivated $ do
        putStrLn "A \"clicked\"-handler to say \"destroy\""
        widgetDestroy window

    -- Insert the hello-world button into the window.
    set window [ containerChild := button ]

    -- The final step is to display this newly created widget. Note that this
    -- also allocates the right amount of space to the windows and the button.
    widgetShowAll window

    app <- applicationNew

    -- blockTermination: return True to prevent quit, False to allow
    on app blockTermination $ do
        putStrLn "blockTermination"
        return False

    -- willTerminate: handle clean-up etc.
    on app willTerminate $ do
        putStrLn "willTerminate"

    menuBar <- menuBarNew
    applicationSetMenuBar app menuBar
    applicationReady app

    -- All Gtk+ applications must have a main loop. Control ends here
    -- and waits for an event to occur (like a key press or mouse event).
    -- This function returns if the program should finish.
    mainGUI

【问题讨论】:

    标签: haskell gtk2hs


    【解决方案1】:

    您需要发送NSApplicationWillTerminate 信号。

    willTerminate :: ApplicationClass self => Signal self (IO ())
    willTerminate = Signal (connect_NONE__NONE "NSApplicationWillTerminate")
    

    gtk-mac-integration 中的处理方式。

    【讨论】:

    • 你能指出一个具体的例子来说明如何使用willTerminate吗?我已经更改了我原来的问题,包括我在哪里添加了对 willTerminate 的调用,但我不知道我还缺少什么。
    • @RichardCook 不幸的是,我更熟悉 OS X 应用程序的期望,而不是如何在 GTKHS 中做这些事情。如果我记得有关此主题的一些常规 GTK 讨论,您可能希望将 applicationSetUseQuartsAccelerators 设置为 True,因为这就是您获得 Cmd+whatever 绑定的原因,IIRC。 demo app 是否符合您的预期?我认为菜单栏退出不起作用是因为您必须明确设置它以发送mainQuit,就像在演示中所做的那样。
    • 太棒了!我根据OSXDemo.hs 中的代码弄清楚了,并相应地更新了我的问题。谢谢!
    • 所以,blockTerminationwillTerminate 是允许 Cmd-Q 被拦截的信号/事件。实际的解决方法是创建一个默认(空)菜单栏并将其添加到应用程序中。感谢@Jack Henahan 为我指明了正确的方向。
    • @RichardCook 太好了,很高兴你破解了它。我什至没有想到原始 GTK 应用程序不会生成菜单栏,但事后看来这是有道理的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 2015-05-02
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    相关资源
    最近更新 更多