I have an application where I have a JPanel with some rectangles painted on it, based on informations retrived from a list (ref ()), later I change the list and need to repaint the JPanel.
I don’t think I’m doing it right, it’s getting slow. I which I could draw each rectangle in an autonomous way, I mean, if the rectangle ‘wants’ to change it’s color, it changes and that rectangle be automatically changed in the panel.
Can anybody help me? Here are some important snippets of codes I’m using.
(defn fill [g x y c]
(doto g
(.setColor c)
(.fillRect
(+ *margin* (* y 15))
(+ *margin* *margin-top* (* x 15))
15 15)))
(defn draw [g x y c]
(doto g
(.setColor c)
(.drawRect
(+ *margin* (* y 15))
(+ *margin* *margin-top* (* x 15))
15 15)))
(defn make-panel
([]
(proxy [JPanel] []
(paintComponent
[g]
(doseq [i (range *size*)
j (range *size*)]
(let [ v (:color @(get-obj i j))]
(cond
(= v :blue) (fill g i j Color/BLUE)
(= v :red) (fill g i j Color/RED)
:else (draw g i j Color/LIGHT_GRAY))))))))
;; This is how I repaint the frame, after changing the list
(doto *frame*
(.setContentPane (make-panel))
.repaint
(.setVisible true))
Firstly, you don’t need to replace your panel (the
(.setContentPane (make-panel))part), just repaint the old panel.To do the minimal amount of work only when something actually changes you could use the watch facility. If information on all your rectangles is held in a single Ref, you might do something like this:
Here
update-rects-as-appropriatestands for code which calculates rectangle colours based on theoldandnewdata and performs the updates when — and only when — results differ. Depending on the precise form of the data held in the Ref, it might become obvious early in the process that there will be no difference, so the whole calculation doesn’t need to be carried out.If each rectangle has a Ref to itself, you can just update based on the new state:
Here
the-rectis the rectangle corresponding tothe-refandupdate-recta function which knows how to update it based on the state ofthe-ref.