Trouble with chart canvas redraw.

58 views
Skip to first unread message

Artem Kozlov

unread,
Apr 2, 2011, 5:48:54 PM4/2/11
to Haskell Charts
Hi.
I am having some troubles with gtk and chart. I want dynamically
update chart as reaction to user input, and also i must properly scale
chart when window is resized.

When button is pressed I am reading value from entry ant pass it to
drawChart action:

initializeControls gui = do
(reDrawButton gui) `on` buttonActivated $ do
counter <- liftM (read :: String -> Double) $ entryGetText (entry
gui)
drawChart gui counter
putStrLn (show counter)
return ()

drawChart gui n = do
let chart = toRenderable $ plotLayout $ plot [1..n] id "TestChart"
let canvas = chartCanvas gui
updateCanvas chart canvas
canvas `onExpose` const (updateCanvas chart canvas)

All seems fine until I not resize window, I have what i need. But
after resize I am seeing chart that was drawing at the first time .
Full code on hpaste: http://hpaste.org/45225/problem_with_canvas_update
Glade file: http://hpaste.org/45226/glade_file
What is my mistake?

Tim Docker

unread,
Apr 3, 2011, 11:09:43 PM4/3/11
to haskell...@googlegroups.com, Artem Kozlov
Hi,

> All seems fine until I not resize window, I have what i need. But
> after resize I am seeing chart that was drawing at the first time .
> Full code on hpaste: http://hpaste.org/45225/problem_with_canvas_update
> Glade file: http://hpaste.org/45226/glade_file
> What is my mistake?

I think this program doesn't have quite the right gtk usage. I'm not an
expert, but my understanding is that:
- expose events should be set up on widget construction
- redrawing should be done via queuing redraw requests

I also thing that, when using the gtk2hs binding one really needs to
keep state in one or more mutable variables. I'm not sure program can be
written without doing this.

I think the code below behaves as you wish.

Tim

module Test where

import Control.Monad
import Data.Accessor((^=))
import Graphics.Rendering.Chart
import Graphics.UI.Gtk
import Graphics.UI.Gtk.Glade
import Data.IORef
import Data.Colour
import Data.Colour.Names
import Graphics.Rendering.Chart.Simple
import Graphics.Rendering.Chart.Gtk

main = do
initGUI
Just xmlGUI <- xmlNew "test.glade"
window <- xmlGetWidget xmlGUI castToWindow "mainWindow"
gui <- initGUIFromGlade xmlGUI
initializeControls gui
onExpose (chartCanvas gui) (drawChart gui)
onDestroy window mainQuit
widgetShowAll window
mainGUI

data GUI = GUI {
entry :: Entry,
reDrawButton :: Button,
chartCanvas :: DrawingArea,
countv :: IORef Double
}

initGUIFromGlade xml = do
countv' <- newIORef 1
entry' <- xmlGetWidget xml castToEntry "entry"
reDrawButton' <- xmlGetWidget xml castToButton "button"
chartCanvas' <- xmlGetWidget xml castToDrawingArea "drawingarea"
return $ GUI {
entry = entry',
reDrawButton = reDrawButton',
chartCanvas = chartCanvas',
countv=countv'
}

initializeControls gui = do
(reDrawButton gui) `on` buttonActivated $ do
counter <- liftM (read :: String -> Double) $ entryGetText (entry gui)

writeIORef (countv gui) counter
widgetQueueDraw (chartCanvas gui)


putStrLn (show counter)
return ()

drawChart gui event = do
n <- readIORef (countv gui)


let chart = toRenderable $ plotLayout $ plot [1..n] id "TestChart"

updateCanvas chart (chartCanvas gui)

Artem Kozlov

unread,
Apr 3, 2011, 12:52:32 PM4/3/11
to Haskell Charts
Tim thanks that pointed me to my misunderstanding. Your solution realy
works.
Maybe you know some open source project that use gtk2hs?

Artem.
Reply all
Reply to author
Forward
0 new messages