Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 自动同时更改JPanel的组件_Java_Multithreading_Swing_Clojure - Fatal编程技术网

Java 自动同时更改JPanel的组件

Java 自动同时更改JPanel的组件,java,multithreading,swing,clojure,Java,Multithreading,Swing,Clojure,我有一个应用程序,其中我有一个JPanel,上面画了一些矩形,基于从列表(ref())中检索到的信息,之后我更改了列表,需要重新绘制JPanel 我觉得我做得不对,速度越来越慢了。我可以用一种自主的方式画出每个矩形,我的意思是,如果矩形“想要”改变它的颜色,它就会改变,并且这个矩形会在面板中自动改变 有人能帮我吗?下面是我正在使用的一些重要代码片段 (defn fill [g x y c] (doto g (.setColor c) (.fillRect (+

我有一个应用程序,其中我有一个JPanel,上面画了一些矩形,基于从列表
(ref())
中检索到的信息,之后我更改了列表,需要重新绘制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))

首先,您不需要更换面板(
(.setContentPane(makepanel))
部分),只需重新绘制旧面板即可

只有当某些事情发生实际变化时,你才可以使用手表设备来完成最少量的工作。如果所有矩形的信息都保存在一个引用中,则可以执行以下操作:

(add-watch the-ref :update-rects
  (fn [_ _ old new]
    (update-rects-as-appropriate old new)))
此处,
update rects as applicate
表示根据
old
new
数据计算矩形颜色的代码,并且仅在结果不同时执行更新。根据Ref中保存的数据的精确形式,在过程的早期可能很明显没有差异,因此不需要进行整个计算

如果每个矩形本身都有一个引用,则可以根据新状态进行更新:

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

这里的
rect
是与
ref
update rect
相对应的矩形,一个知道如何根据
ref
的状态进行更新的函数,真不错!我不知道这个手表厂。这将有很大帮助,我只有一个问题:在这个更新rects函数中,我将更改矩形的状态(颜色),但我会有另一个副作用,那就是重新绘制JPanel,你知道如何只更改面板中我想要的矩形,而不必重新绘制整个内容吗?@jonathancardoso:你必须适当地实现
paintComponent
,并设计一种方法让手表注册矩形的待定更新。手表在任何情况下都需要
(.重新喷漆面板)
;对于他们来说,一种可能的方法是将
[[i j]color]
条目(与它们的矩形对应的
[i j]
)添加到Atom/a Ref中保存的映射中,然后
paintComponent
可以在该映射上迭代,例如
(doseq[[i j]color]更新Atom](cond(=颜色:蓝色)(填充g i j颜色/蓝色)…)
。或者您可能无法让手表调用
。重新绘制
,但可以从单独的线程执行,例如每秒60次。。。嗯,老实说,我根本没有做多少GUI编程。也许有人谁知道更多关于在秋千绘图将有一个更好的解决方案。。。如果他们碰巧是Java用户,我愿意将其转录到Clojure中,并同意我这样做。:-)你帮了我很多,这很有效,而且速度更快。通过重新绘制面板并调用
(SwingUtilities/updateComponentTreeUI*frame*)