import java.awt.BorderLayout; import java.awt.EventQueue; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.LinkedList; import java.util.List; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.*; import java.lang.ref.WeakReference; public class EventQueueFailure2 extends JPanel { public EventQueueFailure2() { add(new JButton(new ButtonAction())); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { createAndShowGUI(); } }); } private static void createAndShowGUI() { JFrame frame = new JFrame("EventQueueFailure2"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); EventQueueFailure2 panel = new EventQueueFailure2(); frame.getContentPane().add(panel); frame.pack(); frame.setVisible(true); } private static final class ButtonAction extends AbstractAction { public ButtonAction() { putValue(Action.NAME, "Push Me"); } public void actionPerformed(ActionEvent e) { RepaintManager.setCurrentManager( new CheckThreadViolationRepaintManager()); SimpleProgressDialog dialog = new SimpleProgressDialog(); dialog.pack(); dialog.setVisible(true); MyEventQueue myEventQueue = new MyEventQueue(); Toolkit.getDefaultToolkit().getSystemEventQueue().push(myEventQueue); // at this point current thread is not an EDT any more for (int i = 0; i < 10; i++) { try { Thread.currentThread().sleep(100); } catch (InterruptedException ex) { ex.printStackTrace(); } EventQueue.invokeLater(new ProgressSetter(dialog, i)); } // exchanging next two lines does not make a difference EventQueue.invokeLater(new DialogCloser(dialog)); myEventQueue.close(); } } private static final class MyEventQueue extends EventQueue { public MyEventQueue() { } public void close() { super.pop(); } } private static final class SimpleProgressDialog extends JDialog { private JProgressBar progressBar; private JLabel progressLabel; public SimpleProgressDialog() { progressBar = new JProgressBar(); progressBar.setMinimum(0); progressBar.setMaximum(10); progressLabel = new JLabel("Performing work ..."); JPanel panel = new JPanel(new BorderLayout()); panel.add(progressBar, BorderLayout.CENTER); panel.add(progressLabel, BorderLayout.SOUTH); getContentPane().add(panel); } public void setProgress(int progress) { progressBar.setValue(progress); } } private static final class ProgressSetter implements Runnable { private SimpleProgressDialog dialog; private int progress; public ProgressSetter(SimpleProgressDialog dialog, int progress) { this.dialog = dialog; this.progress = progress; } public void run() { dialog.setProgress(progress); } } private static final class DialogCloser implements Runnable { private SimpleProgressDialog dialog; public DialogCloser(SimpleProgressDialog dialog) { this.dialog = dialog; } public void run() { dialog.setVisible(false); } } /* * Copyright 2006 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /** *

This class is used to detect Event Dispatch Thread rule violations
* See How to Use Threads * for more info

*

*

This is a modification of original idea of Scott Delap
* Initial version of ThreadCheckingRepaintManager can be found here
* Easily Find Swing Threading Mistakes *

* * @author Scott Delap *

* some improvements from Alexander Potochkin * * https://swinghelper.dev.java.net/ */ private static final class CheckThreadViolationRepaintManager extends RepaintManager { // it is recommended to pass the complete check private boolean completeCheck = true; private WeakReference lastComponent; public CheckThreadViolationRepaintManager(boolean completeCheck) { this.completeCheck = completeCheck; } public CheckThreadViolationRepaintManager() { this(true); } public boolean isCompleteCheck() { return completeCheck; } public void setCompleteCheck(boolean completeCheck) { this.completeCheck = completeCheck; } public synchronized void addInvalidComponent(JComponent component) { checkThreadViolations(component); super.addInvalidComponent(component); } public void addDirtyRegion(JComponent component, int x, int y, int w, int h) { checkThreadViolations(component); super.addDirtyRegion(component, x, y, w, h); } private void checkThreadViolations(JComponent c) { if (!SwingUtilities.isEventDispatchThread() && (completeCheck || c.isShowing())) { boolean repaint = false; boolean fromSwing = false; boolean imageUpdate = false; StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace(); for (StackTraceElement st : stackTrace) { if (repaint && st.getClassName().startsWith("javax.swing.")) { fromSwing = true; } if (repaint && "imageUpdate".equals(st.getMethodName())) { imageUpdate = true; } if ("repaint".equals(st.getMethodName())) { repaint = true; } } if (imageUpdate) { //assuming it is java.awt.image.ImageObserver.imageUpdate(...) //image was asynchronously updated, that's ok return; } if (repaint && !fromSwing) { //no problems here, since repaint() is thread safe return; } //ignore the last processed component if (lastComponent != null && c == lastComponent.get()) { return; } lastComponent = new WeakReference(c); System.out.println(); System.out.println("EDT violation detected"); System.out.println(c); for (StackTraceElement st : stackTrace) { System.out.println("\tat " + st); } } } } }