背景:DIO想当吃播网红,嚷嚷着要JOJO去拿外卖,JOJO不服,让DIO写个投票小程序,在网友的见证下直播投票来决定谁去拿外卖。首先,JOJO仿照饿了么提出了需求。
需求:按空格生成0-99的随机整数,当前最小的数标记为“喂人民服务”。数字输出界面最多显示当前的10个数,且最小数总是显示在界面上的。
分析:主要是显示容器的选择,这里选择java.swing.JFrame来做界面容器,java.swing.Box来配置布局。添加JPanel监听键盘,JPanel内装配JTextArea显示抽奖结果,抽奖结果则存放在ArrayList中。抽奖时使用随机数算法直接调用java.lang.Math或java.util.Random中API
程序代码:
package com.oz.gacha;
import javax.swing.JFrame;
import javax.swing.Box;
import javax.swing.JLabel;
import java.awt.Font;
import com.oz.gacha.MyGachaJPanel;
/*
* DIO用THE WORLD暂停时间后,极限速度下编写的抽奖用的窗口框架,
* 这是一个顶层容器用于组合抽奖面板以实现抽奖的界面
*
* @Author OliverZang
*/
public class MyGachaJFrame extends JFrame{
/*垂直盒容器,内嵌2个水平盒容器用于界面布局*/
private Box parentBox;
private Box nestedLabelBox;
private Box nestedGachaBox;
//组合放置于水平容器内的抽奖组件
private MyGachaJPanel gachaPanel;
//组合放置于水平容器内的抽奖标签
private JLabel gachaLabel;
/*
* 抽奖窗口框架的默认构造器,使用后会生成一个置中,大小硬编码的,DIO不想改css的抽奖
* 完整窗口界面
*/
public MyGachaJFrame(){
/* 创建3个Box容器 */
nestedLabelBox = Box.createHorizontalBox();
nestedGachaBox = Box.createHorizontalBox();
parentBox = Box.createVerticalBox();
/* 平平无奇的标签,装载入一个水平盒容器内 */
gachaLabel = new JLabel("按空格投票,数字最小的去拿外卖");
gachaLabel.setFont(new Font("宋体",Font.PLAIN,16));
nestedLabelBox.add(gachaLabel);
/* 将之前的抽奖面板装载入另一个水平盒容器 */
gachaPanel = new MyGachaJPanel();
nestedGachaBox.add(gachaPanel);
/* 两个水平容器一次放入垂直容器,组成高达(误)*/
parentBox.add(nestedLabelBox);
parentBox.add(nestedGachaBox);
/* 框架装配次级组件,添加面板键盘监听,设置窗口大小,
设置程序关闭条件,设置窗口可视化 */
setContentPane(parentBox);
addKeyListener(gachaPanel);
setSize(300,250);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
}
}
package com.oz.gacha;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import java.awt.FlowLayout;
import java.awt.Font;
import java.util.ArrayList;
import java.util.regex.*;
/*
* DIO用顶尖智慧编写的抽奖面板类,可以按空格键用来抽取0-99的随机整数,并显示在面板上
*的文本显示框上,这个类可以组合到抽奖框架内完成窗口化。
*
* @Author OliverZang
*/
public class MyGachaJPanel extends JPanel implements KeyListener{
private JTextArea gachaResults; //抽奖结果的显示文本框
private ArrayList<String> gachaList; //抽奖结果的存放表单
private static final String TAG = " 喂人民服务"; //标签表示持有者去拿外卖
/*
* 默认的抽奖界面构造器,生成能够满足JOJO需求的界面配置
*/
public MyGachaJPanel(){
gachaList = new ArrayList<>();
//awt界面布局流式,默认置中
setLayout(new FlowLayout());
/* 初始化文本框,10行1列,字体设置,设置不可编辑去除光标*/
gachaResults = new JTextArea(10,1);
gachaResults.setFont(new Font("黑体",Font.BOLD,14));
gachaResults.setEnabled(false);
//抽奖面板组件添加抽奖文本框
add(gachaResults);
}
/*
* 监听键盘按下事件,每次触发执行抽奖并显示结果
* @Param e 触发按键事件
*/
@Override
public void keyPressed(KeyEvent e) {
/*如果是空格,就抽一次奖,修改抽奖表,清空文本显示框,然后重新按列表填写文本框*/
if (e.getKeyCode()==32){
String result = gacha();
modifyList(result);
gachaResults.setText("");
for(String s:gachaList){
gachaResults.append(s + "\n");
}
}
}
/*
*一次抽奖,返回一个0-99的随机整数
*/
public String gacha(){
int randomNum = (int)(Math.random()*100);
String result = String.valueOf(randomNum);
return result;
}
/*
* 用于抽奖后,对于抽奖列表的修改。
* 列表会对最小值附加TAG,表示此数的抽取者去拿外卖
* 每次修改,列表会检查修减保持最多10行数据
* @Param result
* 一次抽奖后得到的数值字符串
*/
public void modifyList(String result){
//Pattern和Matcher组合,用于捕获字符串中的数字部分
String pattern = "\\d+";
Pattern ptn = Pattern.compile(pattern);
Matcher mtr = null;
//用于记录Tag在列表的位置
int tagId = 0;
//如果抽奖表空,第一数字总是最小的,添加Tag
if(gachaList.size()==0){
gachaList.add(result + TAG);
}
//如果抽奖表非空,需要找到带有Tag的最小数字符串
else{
for(int i=0;i<gachaList.size();i++){
//利用正则取到长度>2的字符串中的数字部分
if(gachaList.get(i).length()>2){
tagId = i;
mtr = ptn.matcher(gachaList.get(i));
mtr.find();
//将之前的最小值与当前抽取的值相比,如果后者更小则将Tag传递给后者
if (Integer.parseInt(mtr.group())> Integer.parseInt(result)){
gachaList.set(i,mtr.group());
gachaList.add(result + TAG);
//此时Tag位于表底部
tagId = gachaList.size()-1;
break;
}else{
gachaList.add(result);
break;
}
}
}
}
//添加完数据,还需要修减下列表显示内容,限定为10行
if(gachaList.size()>10){
//删除不持有Tag且最靠近头部的一行,即头部持有Tag就删第二行
if(tagId != 0)
gachaList.remove(0);
else
gachaList.remove(1);
}
}
@Override
public void keyReleased(KeyEvent e){}
@Override
public void keyTyped(KeyEvent e){}
}
测试
package com.oz;
import com.oz.gacha.*;
public class Test1{
public static void main(String[] args){
MyGachaJFrame myFrame = new MyGachaJFrame();
}
}
结果:
结论:java自带的古董swing体验了下,有点和以前写Android一样的感觉。模拟了个抽奖,高亮功能是这辈子不可能做的,要使用支持HTML的JTextPane太麻烦。