これは標準的な方法で可能ですか?java swingイベントキューをクリアする
ここにシナリオがあります。
EDTで高価な作業を開始します(高価な操作が終わるまでEDTがブロックされます)。
EDTがブロックされている間、ユーザーはマウスボタンをクリック/ドラッグし続けました。すべてのマウス操作はどこかに記録されます。
EDTが無料の場合(高価なもので済む)、マウスイベントの処理が開始されます。私はステップ3で欲しい
が積み上げられてきたマウスイベントを破棄することです。 EDTが無料の後、新しいマウスイベントは通常の方法で処理する必要があります。
これを達成する方法に関するアイデア。
PS:EDTがブロックされないようにすることはできません(プログラムの一部のモジュールの動作を制御しません)。
EDIT: 「SunToolkit.flushPendingEvents()」を安全に呼び出せれば、EDTで高価な操作を開始する前に常にガラス板を置くことができます。高価な操作がEDTスレッドを超えたら、すべてのイベントをフラッシュします。何もしないガラスパネルに移動します。その後、EDTを正常に動作させます。
EDIT2: 問題を示すためにSSCCEを追加しました。
public class BusyCursorTest2 extends javax.swing.JFrame { public BusyCursorTest2() { javax.swing.JButton wait = new javax.swing.JButton("Wait 3 seconds"); getContentPane().setLayout(new java.awt.GridLayout(2, 1, 0, 0)); getContentPane().add(wait); getContentPane().add(new javax.swing.JToggleButton("Click me")); setTitle("Busy Cursor"); setSize(300, 200); setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); setVisible(true); wait.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent event) { final java.util.Timer timer = switchToBusyCursor(BusyCursorTest2.this); try { //do something expensive in EDT try { Thread.sleep(3000); } catch (InterruptedException e) { //do nothing } } finally { switchToNormalCursor(BusyCursorTest2.this, timer); } } }); } public static java.util.Timer switchToBusyCursor(final javax.swing.JFrame frame) { startEventTrap(frame); java.util.TimerTask timerTask = new java.util.TimerTask() { public void run() { startWaitCursor(frame); } }; final java.util.Timer timer = new java.util.Timer(); timer.schedule(timerTask, DELAY_MS); return timer; } public static void switchToNormalCursor(final javax.swing.JFrame frame, final java.util.Timer timer) { timer.cancel(); stopWaitCursor(frame); stopEventTrap(frame); } private static void startWaitCursor(javax.swing.JFrame frame) { frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.WAIT_CURSOR)); frame.getGlassPane().addMouseListener(mouseAdapter); frame.getGlassPane().setVisible(true); } private static void stopWaitCursor(javax.swing.JFrame frame) { frame.getGlassPane().setCursor(java.awt.Cursor.getPredefinedCursor(java.awt.Cursor.DEFAULT_CURSOR)); frame.getGlassPane().removeMouseListener(mouseAdapter); frame.getGlassPane().setVisible(false); } private static void startEventTrap(javax.swing.JFrame frame) { frame.getGlassPane().addMouseListener(mouseAdapter); frame.getGlassPane().setVisible(true); } private static void stopEventTrap(javax.swing.JFrame frame) { frame.getGlassPane().removeMouseListener(mouseAdapter); frame.getGlassPane().setVisible(false); } private static final java.awt.event.MouseAdapter mouseAdapter = new java.awt.event.MouseAdapter() { }; public static void main(String[] args) { javax.swing.SwingUtilities.invokeLater(new Runnable() { public void run() { new BusyCursorTest2(); } }); } private static final int DELAY_MS = 250; }
ファイル名を指定して実行ボタンをSSCCE
クリックして "3秒待ち"。高価な操作をシミュレートします。マウスカーソルがビジーに変わります。
カーソルがビジー状態のときに、「クリックしてください」トグルボタンをクリックします。 3秒後にトグルボタンが状態を変えた場合、マウスイベントはトグルボタンで受信され、トラップされませんでした。
カーソルがビジー状態になっている間に、生成されたマウス(およびその他の)イベントは破棄されます。
ありがとうございました。
いいえ、ほとんどのスイングコンポーネント(すべてのパネルとその内容など)はさまざまな開発者によって行われ、それらはいつでも変更される可能性があります。私はそれらのスイングコンポーネントについて何も仮定することはできません。私はルートペイン上に目に見えるガラス板を作って、出来事を得るのを防ぐことができます。 –
2つのソリューションがあります。 1)高価なopsをワーカースレッドに入れます。 2)他のイベントをブロックするためにガラス板を使用する。スイングは開発者からアプリを保護するようには設計されていません。 –
EventQueueとの整合性を変更または分割するには良い方法ではなく、このフォーラムで最も深い検索を行うことで、 'EventQueue theQueue = getToolkit()。getSystemEventQueue();' EDTにイベントを手動で送信すると、待っているスレッドが失われ、現在の形で永遠に残っている、単純にそれをしないでください。 – mKorbel