在左侧面板上,我希望我的JLabel移动到框内的随机位置,在右侧面板上,我希望我的JLabel经常更新当前时间,同时移动到框内的随机位置。
我现在收到的问题是,当我设置JLabel的时间和位置时,我左边的JLabel会出现问题。它首先出现在它的初始位置(开箱顶部),然后在每个它应该移动的位置移动到它的随机位置。
我有一个实现runnable的类来处理左边的JLabel,另一个类也实现了runnable,它通过时间更新来处理JLabel。
任何人都可以帮我解决这个问题吗?我希望这个程序以这种方式设置,2个类实现runnable来处理JLabels移动。
这是关注左侧小组的类:
public class MoveDisplay {
private GUIFrame gui;
private boolean moving = true;
public MoveDisplay(GUIFrame gui) {
this.gui = gui;
}
public void start() {
moving = true;
Random rand = new Random();
while (moving) {
int x = rand.nextInt(150) + 1;
int y = rand.nextInt(150) + 1;
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
gui.moveDisplay(x, y, 100, 100);
}
} );
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stop() {
moving = false;
}
}
这是正确的面板,它是时钟。
public class MoveClock {
private GUIFrame gui;
private boolean clock = true;
private volatile boolean running = true;
public MoveClock(GUIFrame gui) {
this.gui = gui;
}
public void start() {
clock = true;
Random rand = new Random();
while (clock) {
Calendar cal = Calendar.getInstance();
int hour = cal.get(Calendar.HOUR_OF_DAY);
int minute = cal.get(Calendar.MINUTE);
int second = cal.get(Calendar.SECOND);
gui.Klockan(hour, minute, second);
int a = rand.nextInt(100) + 1;
int b = rand.nextInt(100) + 1;
java.awt.EventQueue.invokeLater(new Runnable() { //Utan detta så kör inte Klockan random placeringar
public void run() {
gui.moveClock(a, b, 150, 150);
}
} );
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void stop() {
clock = false;
}
}
这就是所有Frame,Jpanels等所有类:
private JLabel movingDisplay;
private JLabel movingClock;
private MP3Player mp3_player;
private boolean playing = true;
private boolean moving = true;
private boolean clocking = true;
// private Thread t1;
JDialog playingDialog;
private MoveDisplay moveDisplay;
private MoveClock moveClock;
Clip clip;
/**
* Starts the application
*/
public void Start() {
frame = new JFrame();
frame.setBounds(0, 0, 494, 437);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//frame.setLayout(null);
frame.setTitle("Multiple Thread Demonstrator");
InitializeGUI(); // Fill in components
frame.setVisible(true);
frame.setResizable(false); // Prevent user from change size
frame.setLocationRelativeTo(null); // Start middle screen
moveDisplay = new MoveDisplay(this);
moveClock = new MoveClock(this);
}
JPanel pnlDisplay = new JPanel();
Border b2 = BorderFactory.createTitledBorder("Display Thread");
pnlDisplay.setBorder(b2);
pnlDisplay.setBounds(12, 118, 222, 269);
pnlDisplay.setLayout(null);
// Add buttons and drawing panel to this panel
btnDisplay = new JButton("Start Display");
btnDisplay.setBounds(10, 226, 121, 23);
pnlDisplay.add(btnDisplay);
btnDStop = new JButton("Stop");
btnDStop.setBounds(135, 226, 75, 23);
pnlDisplay.add(btnDStop);
pnlMove = new JPanel();
pnlMove.setBounds(10, 19, 200, 200);
Border b21 = BorderFactory.createLineBorder(Color.black);
pnlMove.setBorder(b21);
pnlDisplay.add(pnlMove);
// Then add this to main window
frame.add(pnlDisplay);
// The moving graphics outer panel
JPanel pnlTriangle = new JPanel();
Border b3 = BorderFactory.createTitledBorder("Triangle Thread");
pnlTriangle.setBorder(b3);
pnlTriangle.setBounds(240, 118, 222, 269);
pnlTriangle.setLayout(null);
// Add buttons and drawing panel to this panel
btnTriangle = new JButton("Start Rotate");
btnTriangle.setBounds(10, 226, 121, 23);
pnlTriangle.add(btnTriangle);
btnTStop = new JButton("Stop");
btnTStop.setBounds(135, 226, 75, 23);
pnlTriangle.add(btnTStop);
pnlRotate = new JPanel();
pnlRotate.setBounds(10, 19, 200, 200);
Border b31 = BorderFactory.createLineBorder(Color.black);
pnlRotate.setBorder(b31);
pnlTriangle.add(pnlRotate);
// Add this to main window
frame.add(pnlTriangle);
movingDisplay = new JLabel("DisplayThread");
pnlMove.add(movingDisplay);
btnDStop.setEnabled(false);
movingClock = new JLabel("TriangleThread");
pnlRotate.add(movingClock);
btnTStop.setEnabled(false);
btnDisplay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
moving = true;
btnDisplay.setEnabled(false);
btnDStop.setEnabled(true);
startMoveDisplay();
}
});
btnDStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
moving = false;
btnDisplay.setEnabled(true);
btnDStop.setEnabled(false);
startMoveDisplay();
}
});
btnTriangle.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clocking = true;
btnTriangle.setEnabled(false);
btnTStop.setEnabled(true);
startMoveClock();
}
});
btnTStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
clocking = false;
btnTriangle.setEnabled(true);
btnTStop.setEnabled(false);
startMoveClock();
}
});
}
public void startMoveDisplay() {
if(moving) {
new Thread(new Runnable() {
public void run() {
moveDisplay.start();
}
}).start();
} else {
moveDisplay.stop();
}
}
public void startMoveClock() {
if(clocking) {
new Thread(new Runnable() {
public void run() {
moveClock.start();
}
}).start();
} else {
moveClock.stop();
}
}
public void moveDisplay(int x, int y, int width, int height) {
movingDisplay.setBounds(x, y, width, height);
}
public void moveClock(int a, int b, int width, int height) {
movingClock.setBounds(a, b, width, height);
}
public void Klockan(int hour, int minute, int second) {
movingClock.setText(hour + ":" + minute + ":" + second);
}
答案 0 :(得分:2)
它首先出现在它的初始位置(开箱顶部),然后在每个它应该移动的位置移动到它的随机位置。
好吧,你的整个程序使用空布局(这是不正确的,因为Swing被设计为与布局管理器一起使用),除了你添加随机标签的面板之外。
movingDisplay = new JLabel("DisplayThread");
pnlMove.add(movingDisplay);
那就是我看不到你在哪里使用pnlMove.setLayout( null )
。
所以我猜测临时调用了布局管理器,并且在将面板移动到其随机位置之前,将在面板的开头绘制标签。
所以我的推荐是:
不要使用空布局构建GUI(具有随机位置的面板除外)。 Swing旨在与布局管理器一起使用。
不要使用Thread和Thread.sleep()。对于动画使用Swing Timer。当Timer触发时,代码在EDT上执行,你不需要SwingUtilities.invokeLater()。
您希望代码执行的操作是更改标签的位置,因此只需使用setLocation(...)
方法,而不是setBounds()方法。
方法名称不应以大写字母开头。你的大部分名字都是正确的。始终如一!请注意论坛如何突出显示方法名称,例如类名?