gpt4 book ai didi

java - 使用图形界面(按钮)停止java中的循环

转载 作者:行者123 更新时间:2023-12-01 19:01:37 24 4
gpt4 key购买 nike

我用java创建了一个图形界面和2个按钮。

我的目标:

1)当我单击第一个按钮时,有一个处理不同任务的循环(“开始”按钮)。每个循环之间有 10 秒的停止

2) 当我单击第二个按钮时,循环将立即最后一次处理,但随后停止。(我还想弹出一个窗口,显示它已停止,但这不是主要问题,我想我可以做到。)

我尝试了以下代码,但首先我认为它们是解决我的问题的更简单的方法。另外,我可以编译,但它不起作用,循环没有停止,窗口崩溃:

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

globalStop="Run";

while (globalStop.equals("Run")) {

System.out.println("GO");
// Other stuff

// For the break ?
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Logger.getLogger(main.class.getName()).log(Level.SEVERE, null, ex);
}
}
System.out.println("done");
}

}

private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
globalStop = "Stop";
System.out.println("Bouton2");
}
<小时/>

我希望我说得足够清楚,如果情况并非如此,请告诉我,我会重新表述。预先感谢大家的帮助。

最佳答案

我想知道创建一个美国类型的交通信号 GUI 需要多长时间。花了75分钟。我能够快速创建 GUI,因为很多 Swing 都是样板文件。创建一个 GUI 后,您可以为下一个 GUI 复制一些类。

这是交通信号 GUI 的图像。

Traffic signal GUI

当您按下“开始”按钮时,交通信号灯将从绿色循环到黄色再到红色。交通信号灯将永远循环,直到您按下“停止”按钮。

当您按下停止按钮时,交通信号灯将变成红色。它将永远保持红色,直到您按下“开始”按钮。

当交通信号灯循环时按下“开始”按钮,绿色到黄色到红色的循环将重新开始。

基本上,以下步骤向您展示如何创建任何 Swing GUI。我没有按照这个顺序创建代码,但是按照逻辑顺序解释代码是有意义的。那么,让我们深入研究一下代码。

这是 GUI 的模型类。每个 GUI 都需要有自己的模型,与应用程序的模型分开。对于这个 GUI,模型很简单。

package com.ggl.traffic.signal.model;

import java.awt.Dimension;

public class TrafficSignalModel {

public static final int RED_LIGHT_TIME = 15;
public static final int YELLOW_LIGHT_TIME = 5;
public static final int GREEN_LIGHT_TIME = 10;

public static final Dimension LIGHT_SIZE = new Dimension(32, 32);
}

我们在模型中设置信号灯时间以及交通灯的大小。

对于更复杂的 GUI,我们将跟踪模型中的字段值。

接下来,我们有交通信号 GUI 的主类。

package com.ggl.traffic.signal;

import javax.swing.SwingUtilities;

import com.ggl.traffic.signal.view.TrafficSignalFrame;

public class TrafficSignal implements Runnable {

@Override
public void run() {
new TrafficSignalFrame();
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new TrafficSignal());
}

}

此类确保交通信号 GUI 位于 Swing 事件线程上。这就是这个类所做的全部事情。您可以看到如何复制此类来启动任何 GUI。

接下来,我们有 GUI 的 Frame 类。

package com.ggl.traffic.signal.view;

import java.awt.FlowLayout;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JFrame;

public class TrafficSignalFrame {

protected ButtonPanel bPanel;

protected JFrame frame;

protected TrafficSignalPanel tsPanel;

public TrafficSignalFrame() {
createPartControl();
}

protected void createPartControl() {
tsPanel = new TrafficSignalPanel();
bPanel = new ButtonPanel();

bPanel.setTrafficSignalPanel(tsPanel);

frame = new JFrame();
frame.setTitle("Traffic Signal");
frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent event) {
exitProcedure();
}
});


frame.setLayout(new FlowLayout());
frame.add(bPanel.getPanel());
frame.add(tsPanel.getPanel());
frame.pack();
// frame.setBounds(100, 100, 400, 200);
frame.setVisible(true);
}

public void exitProcedure() {
frame.dispose();
System.exit(0);
}

public JFrame getFrame() {
return frame;
}

}

此类是样板文件,除了构成 GUI 的特定 JPanel 之外。如果您的 JFrame 有 JMenu,则可以在此处将 JMenu 连接到 JFrame。

请注意,我没有扩展 JFrame 来创建此类。扩展 Swing 组件的唯一一次是当您重写该组件的一个或多个方法时。如果我需要实际的 JFrame,我会调用 getFrame() 方法。使用 Swing 组件而不是扩展 Swing 组件使我的方法与 Swing 方法分开。

接下来,我们将看看交通信号灯面板。该面板构成交通信号灯中的 3 个灯之一。

package com.ggl.traffic.signal.view;

import java.awt.Color;
import java.awt.Graphics;

import javax.swing.JPanel;

public class TrafficSignalLightPanel extends JPanel {

private static final long serialVersionUID = 1L;

protected boolean lightOn;

protected Color lightColor;
protected Color darkColor;

public TrafficSignalLightPanel(Color lightColor) {
this.lightColor = lightColor;
this.darkColor = Color.WHITE;
this.lightOn = false;
}

public void setLightOn(boolean lightOn) {
this.lightOn = lightOn;
this.repaint();
}

@Override
public void paintComponent(Graphics g) {
if (lightOn) {
g.setColor(lightColor);
} else {
g.setColor(darkColor);
}
g.fillRect(0, 0, getWidth(), getHeight());
}

}

该类扩展了 JPanel,因为我们要重写 PaintComponent 方法。这是一个简单的类。它所做的只是将面板涂成一种颜色或白色。

接下来,我们将看看交通信号面板。该面板创建 3 个灯面板并将它们排列成垂直行。

package com.ggl.traffic.signal.view;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;

import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.border.Border;

import com.ggl.traffic.signal.model.TrafficSignalModel;

public class TrafficSignalPanel {

protected JPanel panel;

protected TrafficSignalLightPanel redLight;
protected TrafficSignalLightPanel yellowLight;
protected TrafficSignalLightPanel greenLight;

public TrafficSignalPanel() {
createPartControl();
}

protected void createPartControl() {
Border border = BorderFactory.createLineBorder(Color.BLACK, 4);

redLight = new TrafficSignalLightPanel(Color.RED);
redLight.setBorder(border);
redLight.setPreferredSize(TrafficSignalModel.LIGHT_SIZE);

yellowLight = new TrafficSignalLightPanel(Color.YELLOW);
yellowLight.setBorder(border);
yellowLight.setPreferredSize(TrafficSignalModel.LIGHT_SIZE);

greenLight = new TrafficSignalLightPanel(Color.GREEN);
greenLight.setBorder(border);
greenLight.setPreferredSize(TrafficSignalModel.LIGHT_SIZE);

panel = new JPanel();
panel.setLayout(new FlowLayout());
panel.setPreferredSize(
new Dimension(TrafficSignalModel.LIGHT_SIZE.width + 10,
TrafficSignalModel.LIGHT_SIZE.height * 3 + 25));

panel.add(redLight);
panel.add(yellowLight);
panel.add(greenLight);
}

public JPanel getPanel() {
return panel;
}

public TrafficSignalLightPanel getRedLight() {
return redLight;
}

public TrafficSignalLightPanel getYellowLight() {
return yellowLight;
}

public TrafficSignalLightPanel getGreenLight() {
return greenLight;
}

}

从 3 个 JPanel 中相当简单地创建一个 JPanel。我设置了 JPanel 的首选大小,因此灯光将处于垂直行中。

接下来,我们将看看按钮面板。您几乎可以将此代码复制到任何具有按钮面板的 GUI 中。

package com.ggl.traffic.signal.view;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JPanel;

import com.ggl.traffic.signal.thread.TrafficSignalCycle;

public class ButtonPanel {

protected JButton startButton;
protected JButton stopButton;

protected JPanel panel;

protected TrafficSignalCycle thread;

protected TrafficSignalPanel tsPanel;

public ButtonPanel() {
this.thread = null;
createPartControl();
}

protected void createPartControl() {
panel = new JPanel();
panel.setLayout(new FlowLayout());

startButton = new JButton("Start");
startButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
if (thread != null) {
thread.stopRunning();
}
tsPanel.getRedLight().setLightOn(false);
tsPanel.getYellowLight().setLightOn(false);
tsPanel.getGreenLight().setLightOn(false);
thread = new TrafficSignalCycle(tsPanel);
thread.start();
}
});

panel.add(startButton);

stopButton = new JButton("Stop");
stopButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
if (thread != null) {
thread.stopRunning();
thread = null;
}
tsPanel.getRedLight().setLightOn(true);
tsPanel.getYellowLight().setLightOn(false);
tsPanel.getGreenLight().setLightOn(false);
}
});

panel.add(stopButton);

setButtonSizes(startButton, stopButton);
}

protected void setButtonSizes(JButton ... buttons) {
Dimension preferredSize = new Dimension();
for (JButton button : buttons) {
Dimension d = button.getPreferredSize();
preferredSize = setLarger(preferredSize, d);
}
for (JButton button : buttons) {
button.setPreferredSize(preferredSize);
}
}

protected Dimension setLarger(Dimension a, Dimension b) {
Dimension d = new Dimension();
d.height = Math.max(a.height, b.height);
d.width = Math.max(a.width, b.width);
return d;
}

public void setTrafficSignalPanel(TrafficSignalPanel tsPanel) {
this.tsPanel = tsPanel;
}

public JPanel getPanel() {
return panel;
}

}

按钮操作非常简单,我可以将它们保留在按钮面板中。如果需要,您可以编写单独的操作类。

最后,这是运行交通灯循环的代码。它是 Thread 类的扩展,因此它可以在 GUI 之外的单独线程中运行。在与 GUI 线程分开的线程中执行工作始终是一个好主意。

package com.ggl.traffic.signal.thread;

import javax.swing.SwingUtilities;

import com.ggl.traffic.signal.model.TrafficSignalModel;
import com.ggl.traffic.signal.view.TrafficSignalLightPanel;
import com.ggl.traffic.signal.view.TrafficSignalPanel;

public class TrafficSignalCycle extends Thread {

protected boolean isRunning;
protected boolean isFinished;

protected TrafficSignalPanel tsPanel;

public TrafficSignalCycle(TrafficSignalPanel tsPanel) {
this.tsPanel = tsPanel;
this.isRunning = true;
this.isFinished = false;
}

@Override
public void run() {
while (isRunning) {
signalLightOn(tsPanel.getGreenLight(), TrafficSignalModel.GREEN_LIGHT_TIME);
signalLightOn(tsPanel.getYellowLight(), TrafficSignalModel.YELLOW_LIGHT_TIME);
signalLightOn(tsPanel.getRedLight(), TrafficSignalModel.RED_LIGHT_TIME);
}
this.isFinished = true;
}

protected void signalLightOn(TrafficSignalLightPanel light, int seconds) {
if (isRunning) {
setLightOn(light, true);
}

for (int i = 0; i < 1000 && isRunning; i++) {
try {
Thread.sleep(1L * seconds);
} catch (InterruptedException e) {
}
}
setLightOn(light, false);
}

protected void setLightOn(final TrafficSignalLightPanel light,
final boolean isLightOn) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
light.setLightOn(isLightOn);

}
});
}

public void stopRunning() {
this.isRunning = false;
while (!isFinished) {
try {
Thread.sleep(10L);
} catch (InterruptedException e) {
}
}
}

}

真正改变信号灯颜色的方法必须在Swing事件线程中执行。这就是 setLightOn 方法通过调用 SwingUtilities 所做的事情。

定时循环有点复杂,因为我们希望能够在几毫秒内停止线程。 isFinished boolean 值确保线程完全停止,以便可以设置灯光。

这是一个相当长的答案,但我希望它对创建 Swing GUI 的任何人都有帮助。

关于java - 使用图形界面(按钮)停止java中的循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12060066/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com