1
+ /*
2
+ * This library is free software; you can redistribute it and/or
3
+ * modify it under the terms of the GNU Lesser General Public
4
+ * License as published by the Free Software Foundation; either
5
+ * version 2.1 of the License, or (at your option) any later version.
6
+ *
7
+ * This library is distributed in the hope that it will be useful,
8
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10
+ * Lesser General Public License for more details.
11
+ *
12
+ * You should have received a copy of the GNU Lesser General Public
13
+ * License along with this library; if not, write to the Free Software
14
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
15
+ */
16
+
17
+ package com .tech .app .functions ;
18
+
19
+ import java .lang .ref .WeakReference ;
20
+
21
+ import javax .swing .JButton ;
22
+ import javax .swing .JComponent ;
23
+ import javax .swing .JEditorPane ;
24
+ import javax .swing .JFrame ;
25
+ import javax .swing .RepaintManager ;
26
+ import javax .swing .SwingUtilities ;
27
+
28
+ /**
29
+ * <p>
30
+ * This class is used to detect Event Dispatch Thread rule violations<br>
31
+ * See <a
32
+ * href="http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html">How
33
+ * to Use Threads</a> for more info
34
+ * </p>
35
+ * <p/>
36
+ * <p>
37
+ * This is a modification of original idea of Scott Delap<br>
38
+ * Initial version of ThreadCheckingRepaintManager can be found here<br>
39
+ * <a href="http://www.clientjava.com/blog/2004/08/20/1093059428000.html">Easily
40
+ * Find Swing Threading Mistakes</a>
41
+ * </p>
42
+ *
43
+ * @author Scott Delap
44
+ * @author Alexander Potochkin
45
+ *
46
+ * https://swinghelper.dev.java.net/
47
+ */
48
+ public class CheckThreadViolationRepaintManager extends RepaintManager {
49
+ // it is recommended to pass the complete check
50
+ private boolean completeCheck = true ;
51
+
52
+ private WeakReference <JComponent > lastComponent ;
53
+
54
+ public CheckThreadViolationRepaintManager (boolean completeCheck ) {
55
+ this .completeCheck = completeCheck ;
56
+ }
57
+
58
+ public CheckThreadViolationRepaintManager () {
59
+ this (true );
60
+ }
61
+
62
+ public boolean isCompleteCheck () {
63
+ return completeCheck ;
64
+ }
65
+
66
+ public void setCompleteCheck (boolean completeCheck ) {
67
+ this .completeCheck = completeCheck ;
68
+ }
69
+
70
+ public synchronized void addInvalidComponent (JComponent component ) {
71
+ checkThreadViolations (component );
72
+ super .addInvalidComponent (component );
73
+ }
74
+
75
+ public void addDirtyRegion (JComponent component , int x , int y , int w , int h ) {
76
+ checkThreadViolations (component );
77
+ super .addDirtyRegion (component , x , y , w , h );
78
+ }
79
+
80
+ private void checkThreadViolations (JComponent c ) {
81
+ if (!SwingUtilities .isEventDispatchThread () && (completeCheck || c .isShowing ())) {
82
+ boolean repaint = false ;
83
+ boolean fromSwing = false ;
84
+ boolean imageUpdate = false ;
85
+ StackTraceElement [] stackTrace = Thread .currentThread ().getStackTrace ();
86
+ for (StackTraceElement st : stackTrace ) {
87
+ if (repaint && st .getClassName ().startsWith ("javax.swing." )) {
88
+ fromSwing = true ;
89
+ }
90
+ if (repaint && "imageUpdate" .equals (st .getMethodName ())) {
91
+ imageUpdate = true ;
92
+ }
93
+ if ("repaint" .equals (st .getMethodName ())) {
94
+ repaint = true ;
95
+ fromSwing = false ;
96
+ }
97
+ }
98
+ if (imageUpdate ) {
99
+ // assuming it is java.awt.image.ImageObserver.imageUpdate(...)
100
+ // image was asynchronously updated, that's ok
101
+ return ;
102
+ }
103
+ if (repaint && !fromSwing ) {
104
+ // no problems here, since repaint() is thread safe
105
+ return ;
106
+ }
107
+ // ignore the last processed component
108
+ if (lastComponent != null && c == lastComponent .get ()) {
109
+ return ;
110
+ }
111
+ lastComponent = new WeakReference <JComponent >(c );
112
+ violationFound (c , stackTrace );
113
+ }
114
+ }
115
+
116
+ protected void violationFound (JComponent c , StackTraceElement [] stackTrace ) {
117
+ System .out .println ();
118
+ System .out .println ("EDT violation detected" );
119
+ System .out .println (c );
120
+ for (StackTraceElement st : stackTrace ) {
121
+ System .out .println ("\t at " + st );
122
+ }
123
+ }
124
+
125
+ public static void main (String [] args ) throws Exception {
126
+ // set CheckThreadViolationRepaintManager
127
+ RepaintManager .setCurrentManager (new CheckThreadViolationRepaintManager ());
128
+ // Valid code
129
+ SwingUtilities .invokeAndWait (new Runnable () {
130
+ public void run () {
131
+ test ();
132
+ }
133
+ });
134
+ System .out .println ("Valid code passed..." );
135
+ repaintTest ();
136
+ System .out .println ("Repaint test - correct code" );
137
+ // Invalide code (stack trace expected)
138
+ test ();
139
+ }
140
+
141
+ static void test () {
142
+ JFrame frame = new JFrame ("Am I on EDT?" );
143
+ frame .setDefaultCloseOperation (JFrame .EXIT_ON_CLOSE );
144
+ frame .add (new JButton ("JButton" ));
145
+ frame .pack ();
146
+ frame .setVisible (true );
147
+ frame .dispose ();
148
+ }
149
+
150
+ // this test must pass
151
+ static void imageUpdateTest () {
152
+ JFrame frame = new JFrame ();
153
+ frame .setDefaultCloseOperation (JFrame .EXIT_ON_CLOSE );
154
+ JEditorPane editor = new JEditorPane ();
155
+ frame .setContentPane (editor );
156
+ editor .setContentType ("text/html" );
157
+ // it works with no valid image as well
158
+ editor .setText ("<html><img src=\" file:\\ lala.png\" ></html>" );
159
+ frame .setSize (300 , 200 );
160
+ frame .setVisible (true );
161
+ }
162
+
163
+ private static JButton test ;
164
+
165
+ static void repaintTest () {
166
+ try {
167
+ SwingUtilities .invokeAndWait (new Runnable () {
168
+ public void run () {
169
+ test = new JButton ();
170
+ test .setSize (100 , 100 );
171
+ }
172
+ });
173
+ } catch (Exception e ) {
174
+ e .printStackTrace ();
175
+ }
176
+ // repaint(Rectangle) should be ok
177
+ test .repaint (test .getBounds ());
178
+ test .repaint (0 , 0 , 100 , 100 );
179
+ test .repaint ();
180
+ }
181
+ }
0 commit comments