响应用户输入
4、完善图形应用程序
为了演示之前学过的所有内容,我们这里借助之前写的一个用户界面(图1http://blog.csdn.net/zhai56565/article/details/8675327),来实现一个计算用户中奖概率的小程序。通过界面我们可以得知每个组件的功能:复选框随机生成会帮主用户随机显示6个数字填入彩票号码中,复选框自己选择则是自己输入彩票号码。过户单击按钮“开始”时,程序将调用线程playing,并生成中奖号码。用户按下停止按钮时,线程停止,再按下重置按钮将清除所有的文本框,以便开始新一轮游戏。
(图1)
MyEvent类实现的3个接口:ActionListener、ItemListener和Runnable。Runnable接口与线程相关。下面列出了MyEvent类的全部源码:
package guessyourchance;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JTextField;
public class MyEvent implements ItemListener , ActionListener , Runnable{
GuessYourChance guessYourChance;
Thread playing;
public MyEvent(GuessYourChance chance)
{
this.guessYourChance = chance;
}
@Override
public void itemStateChanged(ItemEvent e) {
Object item = e.getItem();
if (item == guessYourChance.quickPick)
{
for (int i = 0; i < 6; i++) {
int pick;
do {
pick = (int)Math.floor(Math.random()*50 + 1);
} while (numberGone(pick , guessYourChance.numbers , i));
guessYourChance.numbers[i].setText("" + pick);
}
}
else
{
for (int i = 0; i < 6; i++) {
guessYourChance.numbers[i].setText(null);
}
}
}
void addOneToField(JTextField field)
{
int num = Integer.parseInt("0" + field.getText());
num++;
field.setText("" + num);
}
boolean numberGone(int num , JTextField[] pastNums , int count)
{
for (int i = 0; i < count; i++) {
if (Integer.parseInt(pastNums[i].getText()) == num) {
return true;
}
}
return false;
}
boolean matchedOne(JTextField win , JTextField[] allPicks)
{
for (int i = 0; i < 6; i++) {
String winText = win.getText();
if (winText.equals(allPicks[i].getText())) {
return true;
}
}
return false;
}
@Override
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
if (command.equals("开始")) {
startPlaying();
}
if(command.equals("停止")){
stopPlaying();
}
if (command.equals("重置")) {
clearAllFields();
}
}
void startPlaying()
{
playing = new Thread(this);
playing.start();
guessYourChance.play.setEnabled(false);
guessYourChance.stop.setEnabled(true);
guessYourChance.reset.setEnabled(false);
guessYourChance.quickPick.setEnabled(false);
guessYourChance.personal.setEnabled(false);
}
void stopPlaying()
{
guessYourChance.play.setEnabled(false);
guessYourChance.stop.setEnabled(true);
guessYourChance.reset.setEnabled(true);
guessYourChance.quickPick.setEnabled(true);
guessYourChance.personal.setEnabled(true);
playing = null;
}
void clearAllFields()
{
for (int i = 0; i < 6; i++) {
guessYourChance.numbers[i].setText(null);
guessYourChance.winners[i].setText(null);
}
guessYourChance.got3.setText("0");
guessYourChance.got4.setText("0");
guessYourChance.got5.setText("0");
guessYourChance.got6.setText("0");
guessYourChance.drawings.setText("0");
guessYourChance.years.setText("0");
}
public void run()
{
Thread thisThread = Thread.currentThread();
while (playing == thisThread) {
addOneToField(guessYourChance.drawings);
int draw = Integer.parseInt(guessYourChance.drawings.getText());
float numYears = (float)draw/104;
guessYourChance.years.setText("" + numYears);
int matches = 0;
for (int i = 0; i < 6; i++) {
int ball;
do {
ball = (int)Math.floor(Math.random() * 50 + 1);
} while (numberGone(ball, guessYourChance.winners, i));
guessYourChance.winners[i].setText("" + ball);
if (matchedOne(guessYourChance.winners[i], guessYourChance.numbers)) {
matches++;
}
}
switch(matches)
{
case 3:
addOneToField(guessYourChance.got3);
break;
case 4:
addOneToField(guessYourChance.got4);
break;
case 5:
addOneToField(guessYourChance.got5);
break;
case 6:
addOneToField(guessYourChance.got6);
guessYourChance.stop.setEnabled(false);
guessYourChance.play.setEnabled(true);
playing = null;
}
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
MyEvent类有一个构造函数:MyEvent(GuessYourChance),它将GuessYourChance对象作为参数,这表明要依靠MyEvent来处理用户事件和进行摇奖。
这个类中使用下述方法来完成具体的任务:
clearAllField()方法清空应用程序中所有的文本框,他在用户单击reset按钮时被调用;
addOneToField()方法将文本框的内容转换为整数值,将其加1后再转换为字符串并存储到文本框中。由于所有的文本框存储的都是字符串,要将其作为数字使用,必须采取特殊措施。
numberGone(0方法接受3个参数——已摇出的一个数字、可存储多个JtextField对象的数组和一个计数器。该方法确保中奖号码不包含相同的数字。
matchedOne()方法接受2个参数——一个JtextField对象和一个包含6个JtextField对象的数组。该方法检查用户选中的某个数是否与当前中奖号码中的数字相同。
actionPerformed()方法接收用户单击按钮时引发的事件;
getActionCommand()方法检索按钮的标签,以确定哪个按钮被单击;
startPlaying()方法在开始按钮被单击时调用,该方法禁用4个组件;
stopPlaying()方法在停止按钮被单击时调用,该方法启用出停止按钮以外的所有组件;
ItemStateChanged()方法接受用户选择复选框“随机生成”和“自己选择”时出发的事件。getItem()方法返回一个对象,指出哪个复选框被单击。如果“随机生成”被单击,则生成6个1~50的随机数。作为用户选择的彩票号码;否则清空用户用来输入号码的文本框。
之后需要打开GuessYourChance.java文件,使用下面的语句添加一个新的实例变量,用于存储MyEvent对象:
MyEvent event = new MyEvent(this);
接下来在构造函数GuessYourChance()中,对于每个可接受用户输入的界面组件,调用其方法addItemListener()或addActionListener():
quickPick.addItemListener(event);
personal.addItemListener(event);
stop.addActionListener(event);
play.addActionListener(event);
reset.addActionListener(event);
整个程序已经完成,运行后查看运行结果,下面是我的中奖概率,看来我比较厝呀,十年竟然一个6中4都没有......: