Я собрал это вместе давным-давно. Более чистую версию можно найти по адресу: https://sourceforge.net/p/tus/code/HEAD/tree/tjacobs/ui/ex/ShakeablePanel.java
package tjacobs.ui.ex;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Graphics;
import java.util.Properties;
import java.util.Random;
import javax.swing.JPanel;
import tjacobs.ui.dialogs.ParamDialog;
import tjacobs.ui.dialogs.StandardDialog;
public class ShakeablePanel extends JPanel {
public static final long serialVersionUID = 0;
public static final int SMALL_SHAKE = 3;
public static final int MEDIUM_SHAKE = 8;
public static final int LARGE_SHAKE = 15;
public static final long SHORT_TIME = 300;
public static final long MEDIUM_TIME = 1000;
public static final long LONG_TIME = 2000;
private int xOffset = 0, yOffset = 0;
public ShakeablePanel() {
super();
}
public ShakeablePanel(Component c) {
super(new BorderLayout());
add(c, BorderLayout.CENTER);
}
/**
* Shakes the panel. Will not work right if called in the
* GUI painter thread
* @param width_variance
* @param height_variance
* @param time
*/
public void _shake(int width_variance, int height_variance, long duration) {
long time = System.currentTimeMillis();
long endTime = time + duration;
Random r = new Random(time);
while (System.currentTimeMillis() < endTime) {
xOffset = r.nextInt(width_variance) - width_variance / 2;
yOffset = r.nextInt(height_variance) - height_variance / 2;
repaint();
try {
Thread.sleep(50);
}
catch (InterruptedException ie) {
return;
}
}
xOffset = 0;
yOffset = 0;
repaint();
}
public void shake(int variance, long duration) {
shake(variance, variance, duration);
}
public void shake(final int width_variance, final int height_variance, final long duration) {
Runnable r = new Runnable() {
public void run() {
_shake(width_variance, height_variance, duration);
}
};
Thread t = new Thread(r);
t.start();
}
/**
* Overrides paint in JPanel.
*
* Must override paint and not just paintComponent so
* that children will be shaken as well
*/
public void paint(Graphics g) {
g.translate(xOffset, yOffset);
super.paint(g);
}
public static void main(String[] args) {
final ShakeablePanel sp = new ShakeablePanel();
final ParamDialog pd = new ParamDialog(new String[] {
"Time(SHORT MEDIUM LONG" + ParamDialog.COMBO,
"Shaking(SMALL MEDIUM LARGE" + ParamDialog.COMBO
}) {
/**
*
*/
private static final long serialVersionUID = 1L;
public boolean showApplyButton() {
return true;
}
public void apply() {
Properties p = getProperties();
String time = p.getProperty("Time");
String shaking = p.getProperty("Shaking");
int shake = shaking.equals("SMALL") ? SMALL_SHAKE : shaking.equals("MEDIUM") ? MEDIUM_SHAKE : LARGE_SHAKE;
long tm = time.equals("SHORT") ? SHORT_TIME : time.equals("MEDIUM") ? MEDIUM_TIME : LONG_TIME;
sp.shake(shake, shake, tm);
//sp.shake(MEDIUM_SHAKE, MEDIUM_SHAKE, MEDIUM_TIME);
}
};
Component main = pd.getMainContent();
sp.setLayout(new BorderLayout());
sp.add(main, BorderLayout.CENTER);
//final ShakeablePanel sp = new ShakeablePanel(main);
pd.setMainContent(sp);
StandardDialog.showStandardDialog(pd);
}
}