似乎我的线程没有启动。要么run
方法实际上没有做任何事情,我无法解释。
我的按钮StartRace
上有一个监听器,它应该启动线程,这将增加每个矩形的长度,直到其中一个长度足以被宣布为胜利者(超过窗口的宽度,250px )。
我将最初绘制的所有组件都绘制到屏幕上,但它们从未重新绘制过。我称之为方法的方式有问题吗?我是否有其他不应该嵌套的类?
//--------------------------------------------------------------
// Start a race between blue and red, track the winner
// Use threads to manage each rectangle's movement
// Allow for user interaction, like stopping and starting
//--------------------------------------------------------------
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.Random;
public class ConcurrencyRace extends JFrame
{
private ConcurrencyPanel panel = new ConcurrencyPanel();
private JButton startRace = new JButton("Start The Race!");
private JButton stopRace = new JButton("Stop The Race!");
private JLabel winnerText = new JLabel("Winner: ");
private int blueDraw = 5, redDraw = 5;
private Random rn = new Random();
//-----------------------------------------------------------------
// Creates and displays the main program frame.
//-----------------------------------------------------------------
public ConcurrencyRace() {
super("Concurrency");
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
Container cp = getContentPane();
cp.add(panel, BorderLayout.CENTER);
JPanel p = new JPanel();
p.add(startRace);
p.add(stopRace);
cp.add(p, BorderLayout.NORTH);
cp.add(winnerText, BorderLayout.SOUTH);
pack();
setVisible(true);
}
public static void main (String[] args)
{
ConcurrencyRace tRun = new ConcurrencyRace();
tRun.setVisible(true);
}
private class ConcurrencyPanel extends JPanel
{
public class runnerThread extends Thread {
@Override
public void run() {
while (blueDraw < 250 && redDraw < 250) {
panel.validate();
panel.repaint();
try {
Thread.sleep(200);
} catch (InterruptedException e) {}
}
}
}
public ConcurrencyPanel ()
{
setPreferredSize(new Dimension(600,250));
}
private class ButtonListener implements ActionListener {
runnerThread rectDraw = new runnerThread();
//--------------------------------------------------------------
// Starts the thread to draw each rectangle ("racer")
//--------------------------------------------------------------
public void actionPerformed (ActionEvent event)
{
if (event.getSource() == startRace) {
rectDraw.start();
}
}
}
@Override
public void paintComponent (Graphics page) {
super.paintComponent(page);
page.setColor(Color.blue);
page.fillRect(0,80,blueDraw,20);
page.setColor(Color.red);
page.fillRect(0,120,redDraw,20);
blueDraw += rn.nextInt(10) + 1;
redDraw += rn.nextInt(10) + 1;
page.dispose();
}
}
}
答案 0 :(得分:2)
你永远不会在你的任何一个按钮上添加ActionListener
,所以当它们被激活时没有任何响应
blueDraw
和redDraw
应为ConcurrencyPanel
。blueDraw
和redDraw
应以特定方法完成,可在需要更新时调用。所有这些让我相信你更善于使用Swing Timer
你可以这样做......
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class ConcurrencyRace {
//-----------------------------------------------------------------
// Creates and displays the main program frame.
//-----------------------------------------------------------------
public ConcurrencyRace() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Timer timer = new Timer(200, null);
JFrame frame = new JFrame();
frame.add(new ButtonPane(timer), BorderLayout.NORTH);
frame.add(new RacePane(timer));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static void main(String[] args) {
new ConcurrencyRace();
}
public class ButtonPane extends JPanel {
private JButton startRace = new JButton("Start The Race!");
private JButton stopRace = new JButton("Stop The Race!");
public ButtonPane(Timer timer) {
startRace.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
timer.start();
}
});
stopRace.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
timer.stop();
}
});
setLayout(new GridBagLayout());
add(startRace);
add(stopRace);
}
}
private class RacePane extends JPanel {
private int blueDraw = 5, redDraw = 5;
private Random rn = new Random();
public RacePane(Timer timer) {
timer.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (updateState()) {
((Timer)e.getSource()).stop();
}
}
});
}
protected boolean updateState() {
blueDraw += rn.nextInt(10) + 1;
redDraw += rn.nextInt(10) + 1;
repaint();
return blueDraw >= getWidth() || redDraw >= getWidth();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(600, 250);
}
@Override
public void paintComponent(Graphics page) {
System.out.println(">>");
super.paintComponent(page);
page.setColor(Color.blue);
page.fillRect(0, 80, blueDraw, 20);
page.setColor(Color.red);
page.fillRect(0, 120, redDraw, 20);
}
}
}
这将Timer
作为中心概念,在按钮和竞赛面板之间共享。
我没有添加对生成获胜者通知的支持,这可以通过传递给RacePane