2012-01-31 2 views
2

목록에서 변경된 정보를 기반으로 JPanel에 일부 사각형이 그려져있는 응용 프로그램이 있습니다. 나중에 목록을 변경하고 JPanel을 다시 칠해야합니다.JPanel의 구성 요소를 자율적으로 동시에 변경하십시오.

나는 제대로하고 있다고 생각하지 않는다. 속도가 느려진다. 저는 각 사각형을 자율적으로 그릴 수 있습니다. 즉, 사각형의 색을 변경하고 싶으면 변경하고 그 사각형을 패널에서 자동으로 변경합니다.

아무도 도와 줄 수 있습니까? 다음은 내가 사용중인 코드의 일부입니다.

(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)) 

답변

3

첫째, 당신은 단지 기존의 패널을 다시 칠, 당신의 패널합니다 ((.setContentPane (make-panel)) 부분)을 교체 할 필요가 없습니다.

무언가가 실제로 변경되었을 때만 최소한의 작업을 수행하려면 시계 기능을 사용할 수 있습니다. 모든 사각형에 대한 정보가 하나의 참조에서 개최되는 경우는 다음과 같이 할 수 있습니다 코드에 대한

다음
(add-watch the-ref :update-rects 
    (fn [_ _ old new] 
    (update-rects-as-appropriate old new))) 

update-rects-as-appropriate 기립 oldnew 데이터를 기반으로 사각형의 색상을 계산 할 때 업데이트를 수행합니다 - 그리고 결과가 다를 때만. Ref에 포함 된 정확한 데이터 형식에 따라 차이가 없으므로 프로세스 초기에 분명해질 수 있으므로 전체 계산을 수행 할 필요가 없습니다. 각 사각형 자체에 대한 참조가있는 경우

, 당신은 단지 새로운 상태에 따라 업데이트 할 수 있습니다 : 여기

(add-watch the-ref :update-rect 
    (fn [_ _ _ new] 
    (update-rect the-rect new))) 

the-rectthe-refupdate-rect에가 기반으로 업데이트하는 방법을 알고있는 기능을 해당 직사각형 the-ref의 상태

+0

정말 멋지다! 나는이 시계 시설을 몰랐다. 많은 도움이 될 것입니다. 한 가지 질문이 있습니다.이 업데이트-rects 함수에서 사각형의 상태 (색상)를 변경하지만 JPanel을 다시 칠하는 또 다른 부작용이 있습니다. 변경 방법 만 알고 있습니까? 패널에서 원하는 사각형을 다시 칠할 필요가 없습니다. –

+0

@jonathancardoso :'paintComponent'를 적절하게 구현하고 시계가 직사각형에 대한 보류중인 업데이트를 등록하는 방법을 고안해야합니다. 어떤 경우에도 watch는'(.repaint panel) '할 필요가있다; 하나의 가능한 접근법은'[[ij] color]'항목 (그들의 직사각형에 대응하는'[ij]와 함께)을 Atom/a Ref에 저장된 맵에 추가하는 것입니다. 그러면'paintComponent'가이 맵을 반복 할 수 있습니다 , 예. '(doseq [[i j] color] updates-atom] (cond (= color : blue) (채우기 i i Color/BLUE) ...))'. –

+0

아니면 시계가'.repaint'를 호출 할 수는 없지만 별도의 스레드에서 말하십시오. 예를 들어, 초당 60 회 ... 글쎄, 솔직하게 말해서 GUI 프로그래밍을 전혀하지 않을 것입니다 . 아마도 Swing에서 드로잉에 대해 더 많이 알고있는 사람은 더 나은 솔루션을 갖게 될 것입니다. Java Person이 되려고한다면 Clojure로 복사 할 의향이 있습니다. :-) –

관련 문제