34 votes

Bibliothèque graphique Haskell qui fonctionne dans GHCi sur MacOS X

Existe-t-il une bibliothèque graphique Haskell ou une liaison avec une bibliothèque externe qui remplit les conditions suivantes ?

  1. Peut être utilisé à partir de ghci Je n'ai pas besoin de lier et de redémarrer le programme.
  2. Fonctionne sur MacOS X. (Délicat en conjonction avec 1 !)
  3. Peut faire des graphiques vectoriels simples (lignes, polygones, remplissages et traits simples).
  4. Peut afficher des images bitmap à l'écran. Exemple : blit une image 17x12 .bmp.

?

Veuillez inclure un exemple minimal de code source ou une référence à celui-ci (juste une fenêtre à l'écran, peut-être avec une ligne verte dessinée à l'intérieur) afin que je puisse vérifier les points 1. et 2. en particulier. De même, si l'une de ces demandes de fonctionnalités est plus élaborée (par exemple OpenGL + 4), veuillez inclure une bonne référence.

PS : Concernant les points 1 et 2, je suis au courant de la enableGUI et je suis prêt à l'utiliser. Cependant, la plupart des bibliothèques ont le problème suivant : vous ne pouvez pas exécuter le programme main plusieurs fois et ne sont donc pas admissibles.

Edit : Pour éviter de perdre votre temps, voici une liste de paquets que j'ai essayés :

  • wx - le ghci s'étouffe sur libstdc++
  • sdl - redéfinit main pour être une macro. Uniquement en temps de compilation.
  • GLFW (OpenGL) - Impossible d'exécuter main deux fois, quelque chose comme "échouer parce qu'il ne peut pas installer le gestionnaire d'événement de souris".

0 votes

Il y a évidemment plusieurs candidats : gtk/cairo ; sdl ; opengl ; wx ; qt ; gd ; ... le défi consiste à écrire des programmes de test pour chacun d'entre eux, puis à les tester sur un Mac.

1 votes

Wx est connu pour ne pas fonctionner dans GHCi (problème avec libstdc++ ou autre). Sdl ne fonctionne pas non plus car il fait de la macro magie avec main . J'ai essayé OpenGL et GLFW, mais je peux invoquer main seulement une fois. C'est le bordel, vraiment. J'envie Python, ils ont réussi à obtenir une liaison Tk qui fonctionne aussi sur le Mac.

0 votes

J'ai fait fonctionner OpenVG sur Mac, mais il échoue au point 1. OpenVG n'a pas non plus de support pour le rendu de texte, bien que ce ne soit pas dans les attributions d'OpenVG, c'est un défaut fatal à son adoption. Ce serait bien s'il y avait une liaison Tk maintenue...

15voto

Heinrich Apfelmus Points 7200

EDIT : En fait, je ne suis plus sûr. Plusieurs versions plus tard, il semble que GLFW ne fonctionne plus dans GHCi sous OS X.

Il s'avère que GLFW+OpenGL remplit ces quatre conditions !

  1. Vous devez invoquer ghci avec ghci -framework Carbon .
  2. Vous avez besoin de la EnableGUI.hs que vous pouvez obtenir ici . Notez que vous ne pouvez pas le charger directement dans GHCi, vous devez d'abord le compiler.
  3. OpenGL possède un mode de projection 2D où vous pouvez dessiner des lignes et des polygones.
  4. Les bitmaps peuvent être chargés comme des textures et placés sur des polygones.

Voici un petit exemple qui affiche un bitmap à l'écran. Il y a quelques restrictions sur le bitmap : ses dimensions doivent être une puissance de deux (ici 256) et il doit s'agir d'un fichier de type .tga (ici "Bitmap.tga" ). Mais comme la transparence est prise en charge, ce n'est pas un gros problème.

Vous devriez être en mesure d'appeler main plusieurs fois sans problème. Le point essentiel est que vous ne devez pas appeler GLFW.terminate .

import Graphics.Rendering.OpenGL as GL
import qualified Graphics.UI.GLFW as GLFW
import Graphics.Rendering.OpenGL (($=))

import Control.Monad
import EnableGUI

main = do
    enableGUI
    GLFW.initialize
    -- open window
    GLFW.openWindow (GL.Size 400 400) [GLFW.DisplayAlphaBits 8] GLFW.Window
    GLFW.windowTitle $= "Bitmap Test"

    -- enable alpha channel
    GL.blend         $= GL.Enabled
    GL.blendFunc     $= (GL.SrcAlpha, GL.OneMinusSrcAlpha)
    -- set the color to clear background
    GL.clearColor    $= GL.Color4 0.8 0.8 0.8 0

    -- set 2D orthogonal view inside windowSizeCallback because
    -- any change to the Window size should result in different
    -- OpenGL Viewport.
    GLFW.windowSizeCallback $= \ size@(GL.Size w h) ->
      do
        GL.viewport   $= (GL.Position 0 0, size)
        GL.matrixMode $= GL.Projection
        GL.loadIdentity
        GL.ortho2D 0 (realToFrac w) (realToFrac h) 0

    render <- initialize
    loop render

    GLFW.closeWindow

loop render = do
    -- draw the entire screen
    render
    -- swap buffer
    GLFW.swapBuffers
    -- check whether ESC is pressed for termination
    p <- GLFW.getKey GLFW.ESC
    unless (p == GLFW.Press) $ do
        -- sleep for 1ms to yield CPU to other applications
        GLFW.sleep 0.001
        -- only continue when the window is not closed
        windowOpenStatus <- GLFW.getParam GLFW.Opened
        unless (windowOpenStatus == False) $
            loop render

-- rendering
initialize = do
    -- load texture from file
    GL.texture GL.Texture2D $= Enabled
    [textureName] <- GL.genObjectNames 1
    GL.textureBinding GL.Texture2D $= Just textureName
    GL.textureFilter  GL.Texture2D $= ((GL.Nearest, Nothing), GL.Nearest)
    GLFW.loadTexture2D "Bitmap.tga" []

    return $ do
        GL.clear [GL.ColorBuffer]
        GL.renderPrimitive GL.Quads $ do
            GL.texCoord $ texCoord2 0 0
            GL.vertex   $ vertex3 (0) 256 0
            GL.texCoord $ texCoord2 0 1
            GL.vertex   $ vertex3 (0) (0) 0
            GL.texCoord $ texCoord2 1 1
            GL.vertex   $ vertex3 256 (0) 0
            GL.texCoord $ texCoord2 1 0
            GL.vertex   $ vertex3 256 256 0

-- type signatures to avoid ambiguity
vertex3 :: GLfloat -> GLfloat -> GLfloat -> GL.Vertex3 GLfloat
vertex3 = GL.Vertex3

texCoord2 :: GLfloat -> GLfloat -> GL.TexCoord2 GLfloat
texCoord2 = GL.TexCoord2

color3 :: GLfloat -> GLfloat -> GLfloat -> GL.Color3 GLfloat
color3 = GL.Color3

Voici un exemple de bitmap (qu'il faut convertir en .tga ).

Sample bitmap

0 votes

Merci ! Excellent exemple. Veuillez noter que j'ai dû corriger deux lignes pour le faire fonctionner car la bibliothèque avait été légèrement modifiée.

0 votes

Je l'ai déjà fait mais il semble que vous deviez accepter mes changements d'une manière ou d'une autre.

1 votes

@Nek J'ai creusé un peu et j'ai trouvé votre édition. Apparemment, les modifications sont revues par d'autres personnes que l'auteur et ils l'ont rejetée parce qu'elle était trop mineure ou quelque chose comme ça. Je vais ajouter vos modifications à la main. Merci !

3voto

Heinrich Apfelmus Points 7200

Le site Gtk2Hs remplit toutes les conditions requises si vous utilisez la version X11 du framework gtk2.

Concernant les exigences :

  1. L'utilisation de X11 permet d'éviter de nombreux problèmes.
  2. Installer gtk2 via MacPorts et utiliser l'option +x11 (par défaut). (Cela dit, j'ai eu de nombreux problèmes pour installer gtk2 dans le passé, mais cette fois-ci, cela semblait fonctionner).
  3. Je serais surpris que GTK+ ne puisse pas le faire.
  4. Idem.

Voici un exemple minimal

import Graphics.UI.Gtk

hello :: (ButtonClass o) => o -> IO ()
hello b = set b [buttonLabel := "Hello World"]

main :: IO ()
main = do
    initGUI
    window <- windowNew
    button <- buttonNew
    set window [windowDefaultWidth := 200, windowDefaultHeight := 200,
              containerChild := button, containerBorderWidth := 10]
    onClicked button (hello button)
    onDestroy window mainQuit
    widgetShowAll window
    mainGUI

2voto

caya Points 338

Depuis début 2014, je n'étais pas en mesure d'utiliser la réponse de @heinrich-apfelmus sous Mac OS X. Cet exemple GLFW-b ( lien ) a toutefois fonctionné.

Donc, assurez-vous que vous avez :

$ cabal install glfw-b

et, si vous avez essayé la réponse d'Apfelmus, vous devrez peut-être

$ ghc-pkg list
$ ghc-pkg unregister GLFW-x.x.x.x

car tous deux fournissent Graphics.UI.GLFW et vous obtiendrez un "Ambiguous module name 'Graphics.UI.GLFW'" de ghc. J'ai ensuite essayé le programme d'exemple ci-dessus et cela a fonctionné (Mac OS X, 10.9, Mavericks).

1voto

Grady Player Points 7823

Avez-vous vu le GLFW comme référencé http://plucky.cs.yale.edu/soe/software1.htm

0 votes

J'ai essayé aujourd'hui, et je suis heureux d'annoncer que SOE peut faire 1 et 2, même si certaines autres utilisations de GLFW ne le peuvent pas. Malheureusement, SOE ne peut pas gérer le point 4.

0 votes

J'ai trouvé la solution : l'exemple GLFW qui ne fonctionnait pas appelait GLFW.terminate à la toute fin alors que SOE ne le fait pas.

1voto

amindfv Points 4668

Plus d'informations sur Haskell+GUI+OpenGL sont disponibles dans cette discussion : http://www.haskell.org/pipermail/haskell-cafe/2011-May/091991.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X