Как работает диспетчеризацию событий - Java
Формулировка задачи:
Объясните пожалуйста, как работает диспетчеризация событий.
Для опыта написал вот что:
Здесь создаются 3 кнопки и метка. При нажатии каждой кнопки обработчик дописывает к метке свой номер и ждет 1,5 сек.
Зачем нужен этот invokeLater()? В книге Герберта Шилдта объяснено непонятно. Я быстро нажимаю кнопки в разном порядке и цифры в метке появляются в том же порядке. Очередь вроде работает одинаково что с инвоком, что без него. В чем прикол? Это для меня очень мозголомная тема. О потоках представление имею из его-же книги для начинающих, если что.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class Test
{
String txt = "";
Test ()
{
JFrame wnd = new JFrame("Тестовая прога");
wnd.setBounds(200, 100, 300, 200);
wnd.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
wnd.setLayout(new FlowLayout());
JButton btn1 = new JButton("Click #1");
JButton btn2 = new JButton("Click #2");
JButton btn3 = new JButton("Click #3");
wnd.add(btn1);
wnd.add(btn2);
wnd.add(btn3);
JLabel lab = new JLabel(txt);
wnd.add(lab);
btn1.addActionListener(new ActionListener ()
{
public void actionPerformed (ActionEvent ae)
{
txt += "1,";
lab.setText(txt);
try
{
Thread.sleep(1500);
}
catch (InterruptedException ie)
{
}
}
});
btn2.addActionListener(new ActionListener ()
{
public void actionPerformed (ActionEvent ae)
{
txt += "2,";
lab.setText(txt);
try
{
Thread.sleep(1500);
}
catch (InterruptedException ie)
{
}
}
});
btn3.addActionListener(new ActionListener ()
{
public void actionPerformed (ActionEvent ae)
{
txt += "3,";
lab.setText(txt);
try
{
Thread.sleep(1500);
}
catch (InterruptedException ie)
{
}
}
});
wnd.setVisible(true);
}
public static void main (String args []) throws InterruptedException
{/*
SwingUtilities.invokeLater(new Runnable ()
{
public void run ()
{
new Test ();
}
});*/
new Test ();
}
}Решение задачи: «Как работает диспетчеризацию событий»
textual
Листинг программы
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class UpdateProgress implements ActionListener
{
static final int UP = 1;
static final int DOWN = -1;
JProgressBar pb;
JLabel lab;
static boolean isRunning = false;
int step;
UpdateProgress (JProgressBar pb, JLabel lab, int step)
{
this.pb = pb;
this.lab = lab;
this.step = step;
}
public void actionPerformed (ActionEvent ae)
{
if (UpdateProgress.isRunning)
return;
class SetValueBar implements Runnable
{
JProgressBar pb;
int newVal;
SetValueBar (JProgressBar pb, int newVal)
{
this.pb = pb;
this.newVal = newVal;
}
public void run ()
{
pb.setValue(newVal);
}
}
lab.setText("Start");
// UpdateProgress.isRunning = true; // Это исправление а ...
new Thread (new Runnable ()
{
public void run ()
{
// Это уязвимость.
// После нажатия второй кнопки в процессе создания потока ...
// ... возникла "заминка".
if (step == UpdateProgress.DOWN)
try
{
Thread.sleep(4000);
}
catch (InterruptedException ie)
{
}
UpdateProgress.isRunning = true; // ... первоначально было здесь. Ошибка!
for (int i = pb.getValue(); step > 0 ? i < 20 : i >= 0; i += step)
{
try
{
Thread.sleep(500);
}
catch (InterruptedException ie)
{
}
SwingUtilities.invokeLater(new SetValueBar (pb, i));
}
lab.setText("Ready !");
UpdateProgress.isRunning = false;
}
}).start();
}
}
class Test extends JFrame
{
JProgressBar pb;
JLabel lab;
Test ()
{
super("Тест");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(400, 300, 190, 110);
setLayout(new FlowLayout());
setResizable(false);
JButton btn1 = new JButton("UP");
JButton btn2 = new JButton("DOWN");
pb = new JProgressBar(0, 19);
lab = new JLabel();
btn1.addActionListener(new UpdateProgress (pb, lab, UpdateProgress.UP));
btn2.addActionListener(new UpdateProgress (pb, lab, UpdateProgress.DOWN));
add(btn1);
add(btn2);
add(pb);
add(lab);
setVisible(true);
}
public static void main (String args [])
{
SwingUtilities.invokeLater(new Runnable ()
{
public void run ()
{
new Test ();
}
});
// new Test ();
}
}