英文:
Java move GUI panel While loop
问题
我有一个面板。我想在一个while
循环内,在按下按钮后并且直到满足某个特定条件之前,将面板向左移动,然后向右移动。但是对于这个问题,让我们假设是连续移动的。在完成一次迭代后,它不会继续向左或向右移动。我使用了repaint()
和Thread.sleep(1000)
,但是没有显示任何内容。请帮助我。
while (true) {
for (int i = 0; i < 5; i++) {
jPanel1.setLocation(jPanel1.getLocation().x + 5, jPanel1.getLocation().y);
i++;
try {Thread.sleep(1000);} catch (InterruptedException ex) {}
repaint();
}
for (int i = 0; i < 5; i++) {
jPanel1.setLocation(jPanel1.getLocation().x - 5, jPanel1.getLocation().y);
i++;
try {Thread.sleep(1000);} catch (InterruptedException ex) {}
repaint();
}
}
英文:
I have a panel. I want to move the panel, inside a while
loop, to the left and then to the right, after pressing a button and until a certain condition is met. But for this question let's say continuously. After it finishes an iteration, it doesn't move left or right. I used repaint()
and Thread.sleep(1000)
but nothing shows up. Please help me
while (true) {
for (int i = 0; i < 5; i++) {
jPanel1.setLocation(jPanel1.getLocation().x + 5, jPanel1.getLocation().y);
i++;
try {Thread.sleep(1000);} catch (InterruptedException ex) {}
repaint();
}
for (int i = 0; i < 5; i++) {
jPanel1.setLocation(jPanel1.getLocation().x - 5, jPanel1.getLocation().y);
i++;
try {Thread.sleep(1000);} catch (InterruptedException ex) {}
repaint();
}
}
答案1
得分: 0
我们再次相聚!
我成功地使用 Swing 的 定时器 实现了移动的 JPanel
。
由于您想要移动 JPanel
,您需要将其放置在一个足够大的父级 容器 中,以允许 JPanel
在其中的不同位置放置。您还需要使用一个空的 布局管理器,因为大多数布局管理器会忽略对 setLocation()
方法的调用。
以下是代码后的更多解释。
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.WindowConstants;
public class MovePane implements ActionListener, Runnable {
private static final String START = "Start";
private static final String STOP = "Stop";
private int diff;
private JButton startButton;
private JButton stopButton;
private JFrame frame;
private JPanel jPanel1;
private Timer timer;
public MovePane() {
diff = 10;
}
@Override // jva.awt.event.ActionListener
public void actionPerformed(ActionEvent event) {
String actionCommand = event.getActionCommand();
switch (actionCommand) {
case START:
launchTimer();
break;
case STOP:
stopTimer();
break;
default:
JOptionPane.showMessageDialog(frame,
actionCommand,
"Unhandled",
JOptionPane.WARNING_MESSAGE);
}
}
@Override // java.lang.Runnable
public void run() {
showGui();
}
private JButton createButton(String text, int mnemonic, String tooltip, boolean enabled) {
JButton button = new JButton(text);
button.setMnemonic(mnemonic);
button.setToolTipText(tooltip);
button.setEnabled(enabled);
button.addActionListener(this);
return button;
}
private JPanel createButtonsPanel() {
JPanel buttonsPanel = new JPanel();
startButton = createButton(START, KeyEvent.VK_M, "Sets panel in motion.", true);
buttonsPanel.add(startButton);
stopButton = createButton(STOP, KeyEvent.VK_P, "Stops panel motion.", false);
buttonsPanel.add(stopButton);
return buttonsPanel;
}
private JPanel createMainPanel() {
JPanel mainPanel = new JPanel(null);
mainPanel.setPreferredSize(new Dimension(400, 400));
jPanel1 = new JPanel();
jPanel1.setBounds(10, 200, 50, 50);
jPanel1.setBorder(BorderFactory.createLineBorder(Color.RED, 2, true));
mainPanel.add(jPanel1);
return mainPanel;
}
private void launchTimer() {
if (timer == null) {
timer = new Timer(0, e -> movePanel());
timer.setDelay(500);
}
timer.start();
startButton.setEnabled(false);
stopButton.setEnabled(true);
}
private void stopTimer() {
timer.stop();
startButton.setEnabled(true);
stopButton.setEnabled(false);
}
private void movePanel() {
Point location = jPanel1.getLocation();
if (location.x > 180) {
diff = -10;
}
else if (location.x < 10) {
diff = 10;
}
location.x += diff;
jPanel1.setLocation(location);
}
private void showGui() {
frame = new JFrame("Move");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.add(createButtonsPanel(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new MovePane());
}
}
Swing 是事件驱动的。事件被添加到队列中,然后从队列中读取并执行。设置 JPanel
的位置是一个事件。在循环中调用事件只会向队列中添加大量事件,有些可能会丢失。这就是为什么有 Swing 的 Timer
类。在上面的代码中,我每隔半秒钟更改一次 jPanel1
的位置。
英文:
We meet again!
I managed to implement the moving JPanel
using a Swing timer.
Since you want to move the JPanel
, you need to place it in a parent container that is large enough to allow the JPanel
to be placed in different locations within it. You also need to use a null layout manager because most layout managers will ignore calls to method setLocation()
.
More explanations after the code.
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.WindowConstants;
public class MovePane implements ActionListener, Runnable {
private static final String START = "Start";
private static final String STOP = "Stop";
private int diff;
private JButton startButton;
private JButton stopButton;
private JFrame frame;
private JPanel jPanel1;
private Timer timer;
public MovePane() {
diff = 10;
}
@Override // jva.awt.event.ActionListener
public void actionPerformed(ActionEvent event) {
String actionCommand = event.getActionCommand();
switch (actionCommand) {
case START:
launchTimer();
break;
case STOP:
stopTimer();
break;
default:
JOptionPane.showMessageDialog(frame,
actionCommand,
"Unhandled",
JOptionPane.WARNING_MESSAGE);
}
}
@Override // java.lang.Runnable
public void run() {
showGui();
}
private JButton createButton(String text, int mnemonic, String tooltip, boolean enabled) {
JButton button = new JButton(text);
button.setMnemonic(mnemonic);
button.setToolTipText(tooltip);
button.setEnabled(enabled);
button.addActionListener(this);
return button;
}
private JPanel createButtonsPanel() {
JPanel buttonsPanel = new JPanel();
startButton = createButton(START, KeyEvent.VK_M, "Sets panel in motion.", true);
buttonsPanel.add(startButton);
stopButton = createButton(STOP, KeyEvent.VK_P, "Stops panel motion.", false);
buttonsPanel.add(stopButton);
return buttonsPanel;
}
private JPanel createMainPanel() {
JPanel mainPanel = new JPanel(null);
mainPanel.setPreferredSize(new Dimension(400, 400));
jPanel1 = new JPanel();
jPanel1.setBounds(10, 200, 50, 50);
jPanel1.setBorder(BorderFactory.createLineBorder(Color.RED, 2, true));
mainPanel.add(jPanel1);
return mainPanel;
}
private void launchTimer() {
if (timer == null) {
timer = new Timer(0, e -> movePanel());
timer.setDelay(500);
}
timer.start();
startButton.setEnabled(false);
stopButton.setEnabled(true);
}
private void stopTimer() {
timer.stop();
startButton.setEnabled(true);
stopButton.setEnabled(false);
}
private void movePanel() {
Point location = jPanel1.getLocation();
if (location.x > 180) {
diff = -10;
}
else if (location.x < 10) {
diff = 10;
}
location.x += diff;
jPanel1.setLocation(location);
}
private void showGui() {
frame = new JFrame("Move");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.add(createMainPanel(), BorderLayout.CENTER);
frame.add(createButtonsPanel(), BorderLayout.PAGE_END);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new MovePane());
}
}
Swing is event driven. Events are added to a queue and then read off the queue and performed. Setting the location of a JPanel
is an event. Calling events in a loop just floods the queue with events and some may be lost. That's why there is the Swing Timer
class. In the above code, every half second I change the location of jPanel1
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论