2015-11-12 23 views
9

Sto scrivendo un programma Haskell con funzionalità click-and-drag, quindi con ogni evento movimento del mouse un aggiornamento viene dipinto sulla finestra. Al momento sto usandoQual è il modo giusto per visualizzare gli aggiornamenti di Cairo in Gtk2hs?

renderWithDrawable myCanvas update 

Tuttavia questo è tremolante molto. La mia comprensione è che ho bisogno di creare un drawable separato (una "superficie"?), Renderizzare a quello, e quindi blitarlo sulla finestra dello schermo in una singola operazione. Tuttavia sono confuso sul modo giusto per farlo.

Ho trovato drawWindowBeginPaintRegion, che parla dell'eliminazione dello sfarfallio. Tuttavia è rimosso in Gtk3 in base ai documenti Haddock. Quindi non sono sicuro se dovrei usare questo, in quanto sembra essere deprecato.

Ho anche trovato renderWithSimilarSurface al Cairo, che sembra fare qualcosa di simile.

Non so inoltre in che modo queste funzioni si riferiscono a renderWithDrawable: devo utilizzarle all'interno di tale funzione o cosa?

Qual è il modo giusto per farlo?

Modifica

Questa sembra essere una cosa conosciuta al Cairo. Sto cercando di capire come gestirlo in Haskell.

+0

È possibile pubblicare un esempio indipendente e minimo? – Cactus

+0

@Cactus, non facilmente. Una demo del problema dello sfarfallio avrebbe bisogno di un qualche tipo di animatore o gestore di eventi del mouse per eseguire ripetuti ritocchi, quindi non sarà così piccolo. Anche il grado di sfarfallio sembra variare con la piattaforma. Invece aggiornerò il post con i puntatori alle discussioni sul problema in altre lingue.Disegnare su una PixMap e quindi darne uno schermo allo schermo sembra essere una cosa standard in altre lingue, quindi speravo che esistesse un modo canonico per farlo in Haskell. –

+2

Si potrebbe voler guardare la funzione 'clip'. Ti permetterà di ridisegnare solo ciò di cui hai bisogno (nel tuo caso, il rettangolo iniziale (vecchia posizione) dell'oggetto trascinato e il suo nuovo rettangolo (nuova posizione)). – antoyo

risposta

4

Il modo giusto per farlo è quello di assicurarsi che tutto il disegno viene da dentro esporre eventi, e opera sulla finestra sorteggio fornito dall'evento . È possibile contrassegnare una regione come "sporca" e attivare un evento di esposizione sintetica utilizzando drawWindowInvalidateRect, drawWindowInvalidateRegion o widgetQueueDraw.

Segue un esempio di impostazione rapida della pipeline di disegno. Viene estratto da un tipo personalizzato Viewport, che fa panning in stile Google maps con movimenti fluidi sulle operazioni di trascinamento e rilascio, che ho creato per un side-project qualche tempo fa. Per supportarlo, deve ridisegnare gli eventi di movimento del mouse, quindi affronta un caso d'uso simile al problema descritto. Ho eliso materiale irrilevante con ... per evidenziare i bit importanti. Ho caricato il progetto completo su github proprio ora, quindi puoi consultare il repository per vedere tutti i dettagli di Viewport. (E 'stato anni, però, quindi c'è probabilmente un bel po' di bitrot - non aspettatevi il progetto di costruire solo e correre con i moderni GHCs/pacchetti.)

viewportNew :: Viewport -> IO DrawingArea 
viewportNew v = do 
    da <- drawingAreaNew 
    -- ... 
    on da exposeEvent $ exposeViewport posRef (draw v) 
    -- ... 

exposeViewport :: IORef Position -> RegionRenderer -> EventM EExpose Bool 
exposeViewport posRef draw = do 
    dw  <- eventWindow 
    region <- eventRegion >>= liftIO . regionGetRectangles 
    -- ... 
    liftIO . renderWithDrawable dw $ do 
     -- Cairo() action goes here 
     -- can reference region to decide which things to draw 
     draw region 
    return True -- see documentation of exposeEvent for what this means 

Questo modello dovrebbe approfittare di incorporato di GTK nel doppio buffer e funziona con entrambi i pacchetti gtk e gtk3.

+0

Grazie. Farò un tentativo e, se funziona, contrassegnerò questo come accettato. –