一、设计思路

1.用一个主窗体,在主窗体上放置两个子窗体,一个是文本面板,一个是模拟键盘面板。

2.文本面板分两个子面板,一个是已有文本,一个是输入文本,在带输入文本面板上添加文件监听器,动态改变下一个带输入的key,从而改变面板上的提示输入key。

3.通过java swing绘制好模拟键盘面板,加深键盘颜色动态提示下一个正确的key,并改变当前下压键盘键的颜色,通过paintcomponent方法实现。

4.启动线程记录游戏时间,匹配正确、错误输入字数,动态显示在面板上。

5.PublicData存放所有类共享的数据:key、text、curkey、texttag。

二、具体代码

MainFrame.java(主窗体)

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;import javax.swing.*;public class MainFrame extends JDesktopPane implements ActionListener{ public static void main(String args[]) {try {System.out.println("Test MainFrame.");MainFrame mainframe = new MainFrame();mainframe.setVisible(true);}catch(Exception e) {e.printStackTrace();}}/*** */private static final long serialVersionUID = 1L;  Dimension screen;Toolkit toolkit=Toolkit.getDefaultToolkit();private JMenuBar fMenu;private JMenu fMenuSys;//系统 private JMenu fMenuLx;//练习private JMenuItem fMenuKey;//键盘练习private JMenuItem fMenuExit;//退出private JMenuItem fMenuLoad;//导入文本private JMenuItem fMenuRefresh;//刷新文本private JMenuItem fMenuCoverkb;//隐藏提示键盘private JMenuItem fMenuOpenkb;//打开提示键盘//住窗体有两个子窗体,作为主窗体的属性调用时更加方便JInternalFrame jianpan;Editor edit;boolean isInit=false;JFrame frame;public MainFrame(){ JFrame.setDefaultLookAndFeelDecorated(true);//加上一个边框frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置点击关闭退出程序Container container = frame.getContentPane(); container.add(this, BorderLayout.CENTER); //居中排布,JDesktopPane 放在JFrame上this.setPreferredSize(new java.awt.Dimension(657, 550)); frame.setTitle("疯狂打字通 XXX 2.0 pro max plus");//设置标题Image ico=Toolkit.getDefaultToolkit().getImage("Image/f.gif");frame.setIconImage(ico);//设置窗体上的图片,image和icon的方法不同frame.setResizable(false);//设置窗体不可以被手动修改大小//设置窗体显示位置screen=toolkit.getScreenSize();frame.setLocation((screen.width-800)/2,screen.height/2-600/2);//窗口定位//添加菜单fMenu = new JMenuBar();frame.setJMenuBar(fMenu);fMenu.setPreferredSize(new java.awt.Dimension(392, 23));{fMenuSys = new JMenu();fMenu.add(fMenuSys);fMenuSys.setText("系统(S)");  fMenuSys.setFont(new Font("x",Font.PLAIN,12));fMenuSys.setMnemonic(java.awt.event.KeyEvent.VK_S);//键盘助记符alt组合时激活fMenuSys.setRolloverEnabled(true);//点击后颜色加深,反转效果{fMenuExit = new JMenuItem();fMenuSys.add(fMenuExit);fMenuExit.setText("退出");fMenuExit.addActionListener(this);fMenuExit.setFont(new Font("x",Font.PLAIN,12));fMenuExit.setIcon(new ImageIcon(getClass().getClassLoader().getResource("leave.gif")));//放置标志fMenuLoad = new JMenuItem();fMenuSys.add(fMenuLoad);fMenuLoad.setText("导入文本");fMenuLoad.addActionListener(this);//导入文本按添加监听器fMenuLoad.setFont(new Font("x",Font.PLAIN,12));fMenuLoad.setIcon(new ImageIcon(getClass().getClassLoader().getResource("lx_2.gif")));fMenuCoverkb = new JMenuItem();fMenuSys.add(fMenuCoverkb);fMenuCoverkb.setText("隐藏提示键盘");fMenuCoverkb.addActionListener(this);//按添加监听器fMenuCoverkb.setFont(new Font("x",Font.PLAIN,12));fMenuCoverkb.setIcon(new ImageIcon(getClass().getClassLoader().getResource("exit.gif")));fMenuOpenkb = new JMenuItem();fMenuSys.add(fMenuOpenkb);fMenuOpenkb.setText("打开提示键盘");fMenuOpenkb.addActionListener(this);//按添加监听器fMenuOpenkb.setFont(new Font("x",Font.PLAIN,12));fMenuOpenkb.setIcon(new ImageIcon(getClass().getClassLoader().getResource("Local.gif")));}}{fMenuLx = new JMenu();fMenu.add(fMenuLx);fMenuLx.setText("练习(E)");fMenuLx.setFont(new Font("x",Font.PLAIN,12));fMenuLx.setMnemonic(java.awt.event.KeyEvent.VK_E);fMenuLx.setRolloverEnabled(true);{fMenuKey = new JMenuItem();fMenuLx.add(fMenuKey);fMenuKey.setText("键盘练习");fMenuKey.addActionListener(this);//键盘练习按钮添加监听器fMenuKey.setFont(new Font("x",Font.PLAIN,12));fMenuKey.setIcon(new ImageIcon(getClass().getClassLoader().getResource("lx_1.gif")));fMenuRefresh = new JMenuItem();fMenuLx.add(fMenuRefresh);fMenuRefresh.setText("更换文本");fMenuRefresh.addActionListener(this);//键盘练习按钮添加监听器fMenuRefresh.setFont(new Font("x",Font.PLAIN,12));fMenuRefresh.setIcon(new ImageIcon(getClass().getClassLoader().getResource("xx.gif")));}frame.pack(); //和前面用的setPreferredSize搭配才有用frame.setVisible(true);}} //  实现ActionListener接口的方法public void actionPerformed(ActionEvent e){if(e.getSource()==fMenuLoad){//导入文件try {JFileChooser fd = new JFileChooser();fd.setFileSelectionMode(JFileChooser.OPEN_DIALOG);fd.showOpenDialog(null);File f = fd.getSelectedFile();if (f != null) {String filepath = f.getPath().trim();//读取本地txtStringBuffer buffer = new StringBuffer();BufferedReader bf= new BufferedReader(new FileReader(filepath));String s = null;while((s = bf.readLine())!=null){//使用readLine方法,一次读一行buffer.append(s.trim());}String xml = buffer.toString();PublicData.Text= xml;if(isInit==false){showFrame();isInit=true;}else{this.edit.txtOriginal.setText(PublicData.Text);}}} catch (Exception e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}if(e.getSource()==fMenuExit){//退出按钮int i=JOptionPane.showConfirmDialog(this,"你真的要退出吗?","疯狂打字",JOptionPane.YES_OPTION,JOptionPane.QUESTION_MESSAGE);if(i==0){System.exit(0);}}if(e.getSource()==fMenuCoverkb){//隐藏提示键盘if(jianpan!=null){this.jianpan.setVisible(false);}}if(e.getSource()==fMenuOpenkb){//打开提示键盘if(jianpan!=null){this.jianpan.setVisible(true);}}if(e.getSource()==fMenuKey){//键盘练习按钮PublicData.Text=PublicData.getText((int)(Math.random()*5+1));if(isInit==false){showFrame();isInit=true;}else{JOptionPane.showMessageDialog(new JPanel(),"请先点击刷新文本","提示",JOptionPane.WARNING_MESSAGE);}}if(e.getSource()==fMenuRefresh){//刷新文本按钮if(isInit==false){JOptionPane.showMessageDialog(new JPanel(),"请先点击键盘练习","提示",JOptionPane.WARNING_MESSAGE);}else{PublicData.Text=PublicData.getText((int)(Math.random()*5+1));this.edit.txtOriginal.setText(PublicData.Text);this.edit.txtNewText.setText("");}}}//显示游戏界面private void showFrame(){//显示键盘jianpan=new JInternalFrame();//keyset是jpanel,需要放到JInternalFrame上才能显示jianpan.setBounds(0,326,0,0); jianpan.setPreferredSize(new java.awt.Dimension(800, 223));((javax.swing.plaf.basic.BasicInternalFrameUI) jianpan.getUI()).setNorthPane(null);//隐藏窗体的顶部title barjianpan.putClientProperty("JInternalFrame.isPalette", Boolean.TRUE);//putClientProperty用来为组件设置注释,后面的true意味取消掉窗体边框,不同的组件含义不同jianpan.setVisible(true);jianpan.pack();//搭配setPreferredSize使用,setPreferredSize设置为合适的大小,pack为之分配大小。如果不pack则大小为0Keyset ks=new Keyset();
//      keylistener kl=new keylistener();
//      ks.add(kl);jianpan.add(ks);this.add(jianpan,2);//       //显示文本和输入文本窗体edit=new Editor(this);this.add(edit,2);}
}

Editor.java(文本框)

import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;import javax.swing.text.*;
import javax.swing.*;
import java.awt.*;import javax.swing.event.*;public class Editor extends JInternalFrame implements DocumentListener,Runnable{/*** */private static final long serialVersionUID = 1L;Runtime r=Runtime.getRuntime();MainFrame parent;Document doc;//The Document is a container for text that servesas the model for swing text components. StyledDocument styledDoc = new DefaultStyledDocument();//Interface for a generic styled document.Thread th;private int hour=0;//时private int minute=0;//分private int second=0;//秒//标签private JLabel lblTime;//用时private JLabel lblError;//错误字数private JLabel lblWord;  //总字数private JLabel lblM;private JLabel lblRight;//正确字数private JLabel lblCount;////面板   private JPanel pShowData;//显示文本面板private JPanel pAttrib;//参数显示面板JTextPane txtOriginal;//原始文本JTextPane txtNewText;//输入文本//信息条区域private JTextField txtMW;//每分钟多少字private JTextField txtError;//错误字数显示条private JTextField txtRight;//正确字数显示条private JTextField txtTime;//时间计数显示条private JTextField txtCount;//总输入字数//记录输入的正确和错误的个数据private int rightWord=0;private int errorWord=0;private int rightCount=0;private int errorCount=0;private int wordCount=0;//临时@SuppressWarnings("unused")private boolean temp=true;public Editor(MainFrame parent ){this.parent=parent;th=new Thread(this);//组建Editor用户界面....setBounds(0,0,0,0); this.setPreferredSize(new java.awt.Dimension(657, 325));//内部窗体大小657,325((javax.swing.plaf.basic.BasicInternalFrameUI) this.getUI()).setNorthPane(null);this.putClientProperty("JInternalFrame.isPalette", Boolean.TRUE);getContentPane().setLayout(null);this.setVisible(true);{pAttrib = new JPanel();getContentPane().add(pAttrib, new GridBagConstraints(1, 0, 12, 3, 0.0, 0.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));FlowLayout pAttribLayout = new FlowLayout();pAttrib.setBorder(BorderFactory.createTitledBorder(""));pAttrib.setLayout(pAttribLayout);pAttrib.setBounds(-2, 33, 658, 42);{lblTime = new JLabel();pAttrib.add(lblTime);lblTime.setText("用时:");lblTime.setFont(new java.awt.Font("新宋体", 0, 12));}{txtTime = new JTextField(8);pAttrib.add(txtTime);txtTime.setText("00:00:00");txtTime.setEditable(false);txtTime.setHorizontalAlignment(SwingConstants.CENTER);}{lblCount = new JLabel();pAttrib.add(lblCount);lblCount.setText("总字数:");lblCount.setFont(new java.awt.Font("新宋体", 0, 12));}{txtCount = new JTextField();pAttrib.add(txtCount);txtCount.setColumns(6);txtCount.setText("0");txtCount.setEditable(false);txtCount.setHorizontalAlignment(SwingConstants.CENTER);}{lblRight = new JLabel();pAttrib.add(lblRight);lblRight.setText("正确:");lblRight.setFont(new java.awt.Font("新宋体", 0, 12));}{txtRight = new JTextField();pAttrib.add(txtRight);txtRight.setColumns(4);txtRight.setText("0");txtRight.setEditable(false);txtRight.setHorizontalAlignment(SwingConstants.CENTER);}{lblError = new JLabel();pAttrib.add(lblError);lblError.setText("错误:");lblError.setFont(new java.awt.Font("新宋体", 0, 12));}{txtError = new JTextField();pAttrib.add(txtError);txtError.setColumns(4);txtError.setText("0");txtError.setEditable(false);txtError.setHorizontalAlignment(SwingConstants.CENTER);}{lblM = new JLabel();pAttrib.add(lblM);lblM.setText("每分钟");lblM.setFont(new java.awt.Font("新宋体", 0, 12));}{txtMW = new JTextField();pAttrib.add(txtMW);txtMW.setColumns(4);txtMW.setText("0");txtMW.setEditable(false);txtMW.setHorizontalAlignment(SwingConstants.CENTER);}{lblWord = new JLabel();pAttrib.add(lblWord);lblWord.setText("个字");lblWord.setFont(new java.awt.Font("新宋体", 0, 12));}}{pShowData = new JPanel();//建一个面板来装两个jtextpanegetContentPane().add(pShowData,new GridBagConstraints(1,1,12,10,0.0,0.0,GridBagConstraints.CENTER,GridBagConstraints.BOTH,new Insets(0, 0, 0, 0),0,0));GridLayout pShowDataLayout = new GridLayout(2, 1);pShowDataLayout.setHgap(5);pShowDataLayout.setVgap(5);pShowDataLayout.setColumns(1);pShowDataLayout.setRows(2);pShowData.setLayout(pShowDataLayout);pShowData.setBounds(5, 82, 644, 231);{txtOriginal = new JTextPane(styledDoc);//导入文本pShowData.add(txtOriginal);//把pane放到Jpanel上txtOriginal.setPreferredSize(new java.awt.Dimension(600, 0));txtOriginal.setEditable(false);//设置为不可修改}{txtNewText = new JTextPane();pShowData.add(txtNewText);txtNewText.setPreferredSize(new java.awt.Dimension(600, 0));Document doc=txtNewText.getDocument();doc.addDocumentListener(this);//给文本添加监听器//给输入文本框添加键盘监听器txtNewText.addKeyListener(new KeyAdapter(){public void keyPressed(KeyEvent e){PublicData.curkey=String.valueOf(e.getKeyChar());//转换成string}public void keyTyped(KeyEvent e) {
//                      PublicData.curkey=String.valueOf(e.getKeyChar());}public void keyReleased(KeyEvent e){PublicData.curkey="";//转换成stringparent.repaint();}});}}{txtOriginal.setText(PublicData.Text);PublicData.key=txtOriginal.getText().substring(0,1);//启动线程,文本输入满时清空Empty empty=new Empty();empty.start();}this.pack();//启动线程th.start();}//判断正确和错误的字.并改变它们的颜色public void chDocs(int xLen,int yLen,String xStr,String yStr){SimpleAttributeSet attrSet=new SimpleAttributeSet(); rightWord=0;errorWord=0;for(int i=1;i<=xLen;i++){if(i<=yLen){//数据验证if(xStr.substring(i-1,i).equals(yStr.substring(i-1,i))){rightWord++;StyleConstants.setForeground(attrSet,Color.BLUE);}else{errorWord++;StyleConstants.setForeground(attrSet,Color.RED);}StyleConstants.setUnderline(attrSet,true);}else{StyleConstants.setForeground(attrSet,Color.BLACK);StyleConstants.setUnderline(attrSet,false);}styledDoc.setCharacterAttributes(i-1,1,attrSet,true);}//设置正确、错误字数txtRight.setText((rightWord+rightCount)+"");txtError.setText((errorWord+errorCount)+"");//计算和设置每分钟正确打字数int c=0;for(int i=0;i<minute;i++){c=c+60;}c=c+second;double s=(double)c/60;txtMW.setText(""+Math.round(((double)Integer.parseInt(txtRight.getText()))/s));}//实现DocumentListener所有的方法..用于监听输入文本...,获取即将输入的下一个字符是啥,三个监听都是用来动态改变键盘的下一个输入key是什么public void changedUpdate(DocumentEvent e){PublicData.key=txtOriginal.getText().substring(txtNewText.getText().length(),txtNewText.getText().length()+1);this.parent.repaint();}public void insertUpdate(DocumentEvent e){PublicData.key=txtOriginal.getText().substring(txtNewText.getText().length(),txtNewText.getText().length()+1);this.parent.repaint();}public void removeUpdate(DocumentEvent e){PublicData.key=txtOriginal.getText().substring(txtNewText.getText().length(),txtNewText.getText().length()+1);this.parent.repaint();}//数据验证private void dataValidate(){chDocs(txtOriginal.getText().length(),txtNewText.getText().length(),txtOriginal.getText(),txtNewText.getText());if(txtOriginal.getText().length()>txtNewText.getText().length()){PublicData.key=txtOriginal.getText().substring(txtNewText.getText().length(),txtNewText.getText().length()+1);txtCount.setText((txtNewText.getText().length()+wordCount)+"");}}//计时器public  void run(){try{while(true){Thread.sleep(1000);second++;if(second==60){second=0;minute++;if(minute==60){minute=0;hour++;if(hour==1000){second=0;minute=0;hour=0;}}}txtTime.setText(((hour<=9)?"0":"")+hour+":"+((minute<=9)?"0":"")+minute+":"+((second<=9)?"0":"")+second);}}catch (InterruptedException e){}}//清空文本框的线程class Empty extends Thread{public void run(){while(true){try{Thread.sleep(100);dataValidate();//当文本打完时清空输入框,更新初始文本if(txtNewText.getText().length()>=txtOriginal.getText().length()){txtNewText.setText("");PublicData.Text=PublicData.getText((int)(Math.random()*5+1));txtOriginal.setText(PublicData.Text);parent.repaint();}}catch(InterruptedException e){}}}}
}

Keyset.java(虚拟键盘)

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;public class Keyset extends JPanel implements KeyListener {/*** */private static final long serialVersionUID = 1L;
//创建类的时候自动调用paintComponent方法public void paintComponent(Graphics g){super.paintComponent(g);String str=new String(PublicData.key);//下一个正确的键盘键String cur=(PublicData.curkey);//当前按下的键盘键int curkt=0;//当前按下的键的纵坐标int curkl=0;//当前按下的键的横坐标int keyTop=0;//字符在键盘上的纵坐标int keyLeft=0;//字符在键盘上的横坐标boolean leftShift=false;//是否是左边的Shiftboolean rightShift=false;//是否是右边的Shift@SuppressWarnings("unused")boolean yShift=false;//是否要用Shiftboolean ySpace=false;//是否是空格String shift=new String("~!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVBNM<>?");//需要搭配shift使用的String noShift=new String("`1234567890-=qwertyuiop[]\\asdfghjkl;'zxcvbnm,./");//不需要搭配shiftint LEFT=52;//键盘横坐标int TOP=20;//键盘纵坐标int lTemp=LEFT;int tTemp=TOP;if(shift.lastIndexOf(str)<=46){//计算是不是要用上Shiftif((shift.lastIndexOf(str)>=0 && shift.lastIndexOf(str)<=5) || (shift.lastIndexOf(str)>=13 && shift.lastIndexOf(str)<=17) || (shift.lastIndexOf(str)>=26 && shift.lastIndexOf(str)<=30) || (shift.lastIndexOf(str)>=37 && shift.lastIndexOf(str)<=41)){//计算字符在不在左手区yShift=true;rightShift=true;//提示使用右shift键if(shift.lastIndexOf(str)>=0 && shift.lastIndexOf(str)<=5){//计算字符在该区的位置keyTop=1;for(int i=0;i<=5;i++){if(str.equals(shift.substring(i, i+1))){keyLeft=i;System.out.println(shift.substring(i, i+1));}}}if(shift.lastIndexOf(str)>=13 && shift.lastIndexOf(str)<=17){//计算字符在该区的位置keyTop=2;for(int i=13;i<=17;i++){if(str.equals(shift.substring(i, i+1))){keyLeft=i;}}}if(shift.lastIndexOf(str)>=26 && shift.lastIndexOf(str)<=30){//计算字符在该区的位置keyTop=3;for(int i=26;i<=30;i++){if(str.equals(shift.substring(i, i+1))){keyLeft=i;}}}if(shift.lastIndexOf(str)>=37 && shift.lastIndexOf(str)<=41){//计算字符在该区的位置keyTop=4;for(int i=37;i<=41;i++){if(str.equals(shift.substring(i, i+1))){keyLeft=i;}}}}if((shift.lastIndexOf(str)>=6 && shift.lastIndexOf(str)<=12) || (shift.lastIndexOf(str)>=18 && shift.lastIndexOf(str)<=25) || (shift.lastIndexOf(str)>=31 && shift.lastIndexOf(str)<=36) || (shift.lastIndexOf(str)>=42 && shift.lastIndexOf(str)<=46)){//计算字符在不在右手区yShift=true;leftShift=true;//提示使用左shift键if(shift.lastIndexOf(str)>=6 && shift.lastIndexOf(str)<=12){keyTop=1;for(int i=6;i<=12;i++){if(str.equals(shift.substring(i, i+1))){keyLeft=i;}}}if(shift.lastIndexOf(str)>=18 && shift.lastIndexOf(str)<=25){keyTop=2;for(int i=18;i<=25;i++){if(str.equals(shift.substring(i, i+1))){keyLeft=i;}}}if(shift.lastIndexOf(str)>=31 && shift.lastIndexOf(str)<=36){keyTop=3;for(int i=31;i<=36;i++){if(str.equals(shift.substring(i, i+1))){keyLeft=i;}}}if(shift.lastIndexOf(str)>=42 && shift.lastIndexOf(str)<=46){keyTop=4;for(int i=42;i<=46;i++){if(str.equals(shift.substring(i, i+1))){keyLeft=i;}}}}}if(noShift.lastIndexOf(str)<=46){if(noShift.lastIndexOf(str)>=0 && noShift.lastIndexOf(str)<=12){keyTop=1;for(int i=0;i<=12;i++){if(str.equals(noShift.substring(i,i+1))){keyLeft=i;}}}if(noShift.lastIndexOf(str)>=13 && noShift.lastIndexOf(str)<=25){keyTop=2;for(int i=13;i<=25;i++){if(str.equals(noShift.substring(i,i+1))){keyLeft=i;}}}if(noShift.lastIndexOf(str)>=26 && noShift.lastIndexOf(str)<=36){keyTop=3;for(int i=26;i<=36;i++){if(str.equals(noShift.substring(i,i+1))){keyLeft=i;}}}if(noShift.lastIndexOf(str)>=37 && noShift.lastIndexOf(str)<=46){keyTop=4;for(int i=37;i<=46;i++){if(str.equals(noShift.substring(i,i+1))){keyLeft=i;}}}}//输入字符为空格if(str.equals(" ")){ySpace=true;}//设置当前按下键的位置if(cur!=null&&shift.lastIndexOf(cur)>=0 && shift.lastIndexOf(cur)<=5){//计算字符在该区的位置curkt=1;for(int i=0;i<=12;i++){if(cur.equals(shift.substring(i, i+1))){curkl=i;System.out.println(shift.substring(i, i+1));}}}if(cur!=null&&shift.lastIndexOf(cur)>=13 && shift.lastIndexOf(cur)<=17){//计算字符在该区的位置curkt=2;for(int i=13;i<=25;i++){if(cur.equals(shift.substring(i, i+1))){curkl=i;}}}if(cur!=null&&shift.lastIndexOf(cur)>=26 && shift.lastIndexOf(cur)<=36){//计算字符在该区的位置curkt=3;for(int i=26;i<=30;i++){if(cur.equals(shift.substring(i, i+1))){curkl=i;}}}if(cur!=null&&shift.lastIndexOf(cur)>=37 && shift.lastIndexOf(cur)<=46){//计算字符在该区的位置curkt=4;for(int i=37;i<=41;i++){if(cur.equals(shift.substring(i, i+1))){curkl=i;}}}//noshift的按键if(cur!=null&&noShift.lastIndexOf(cur)>=0 && noShift.lastIndexOf(cur)<=12){curkt=1;for(int i=0;i<=12;i++){if(cur.equals(noShift.substring(i,i+1))){curkl=i;}}}if(cur!=null&&noShift.lastIndexOf(cur)>=13 && noShift.lastIndexOf(cur)<=25){curkt=2;for(int i=13;i<=25;i++){if(cur.equals(noShift.substring(i,i+1))){curkl=i;}}}if(cur!=null&&noShift.lastIndexOf(cur)>=26 && noShift.lastIndexOf(cur)<=36){curkt=3;for(int i=26;i<=36;i++){if(cur.equals(noShift.substring(i,i+1))){curkl=i;}}}if(cur!=null&&noShift.lastIndexOf(cur)>=37 && noShift.lastIndexOf(cur)<=46){curkt=4;for(int i=37;i<=46;i++){if(cur.equals(noShift.substring(i,i+1))){curkl=i;}}}//绘制编辑键区图形,每个按键之间相隔两个横坐标g.setColor(Color.black);for(int i=0;i<=12;i++){if(keyTop==1 && keyLeft==i){g.setColor(Color.gray);g.fillRect(LEFT,TOP,35,35);//填充矩形颜色     }if(curkt==1 && curkl==i){g.setColor(Color.pink);g.fillRect(LEFT,TOP,35,35);//填充矩形颜色    }g.setColor(Color.black);g.draw3DRect(LEFT,TOP,35,35,true);//画出矩形的边框LEFT=LEFT+37;}//画←键g.draw3DRect(LEFT,TOP,70,35,true);int sum=12;LEFT=lTemp;TOP=TOP+37;//Tab键g.draw3DRect(LEFT,TOP,54,35,true);LEFT=LEFT+56;//画键盘的第二排for(int i=1;i<=12;i++){if(keyTop==2 && keyLeft==i+sum){g.setColor(Color.gray);g.fillRect(LEFT,TOP,35,35);}if(curkt==2 && curkl==i+sum){g.setColor(Color.pink);g.fillRect(LEFT,TOP,35,35);}g.setColor(Color.black);g.draw3DRect(LEFT,TOP,35,35,true);LEFT=LEFT+37;}//画|\键sum=sum+12;if(keyTop==2 && keyLeft==sum+1){g.setColor(Color.gray);g.fillRect(LEFT,TOP,51,35);}if(curkt==2 && curkl==sum+1){g.setColor(Color.pink);g.fillRect(LEFT,TOP,51,35);}g.setColor(Color.black);g.draw3DRect(LEFT,TOP,51,35,true);sum=sum+1;LEFT=lTemp;TOP=TOP+37;//Caps Lock键g.draw3DRect(LEFT,TOP,65,35,true);LEFT=LEFT+67;for(int i=1;i<=11;i++){if(keyTop==3 && keyLeft==sum+i){g.setColor(Color.gray);g.fillRect(LEFT,TOP,35,35);}if(curkt==3 && curkl==sum+i){g.setColor(Color.pink);g.fillRect(LEFT,TOP,35,35);}g.setColor(Color.black);g.draw3DRect(LEFT,TOP,35,35,true);LEFT=LEFT+37;}//Enter键g.draw3DRect(LEFT,TOP,77,35,true);sum=sum+11;LEFT=lTemp;TOP=TOP+37;//左Shift键if(leftShift==true){g.setColor(Color.gray);g.fillRect(LEFT,TOP,82,35);}g.setColor(Color.black);g.draw3DRect(LEFT,TOP,82,35,true);LEFT=LEFT+84;for(int i=1;i<=10;i++){if(keyTop==4 && keyLeft==sum+i){g.setColor(Color.gray);g.fillRect(LEFT,TOP,35,35);}if(curkt==4 && curkl==sum+i){g.setColor(Color.pink);g.fillRect(LEFT,TOP,35,35);}g.setColor(Color.black);g.draw3DRect(LEFT,TOP,35,35,true);LEFT=LEFT+37;}//右Shift键if(rightShift==true){g.setColor(Color.gray);g.fillRect(LEFT,TOP,97,35);}g.setColor(Color.black);g.draw3DRect(LEFT,TOP,97,35,true);//左Ctrl键LEFT=lTemp;TOP=TOP+37;g.draw3DRect(LEFT,TOP,53,35,true);LEFT=LEFT+55;//win键g.draw3DRect(LEFT,TOP,44,35,true);LEFT=LEFT+46;//左Alt键g.draw3DRect(LEFT,TOP,44,35,true);LEFT=LEFT+46;//Space键if(ySpace==true){g.setColor(Color.gray);g.fillRect(LEFT,TOP,211,35);}g.setColor(Color.black);g.draw3DRect(LEFT,TOP,211,35,true);//右Alt键LEFT=LEFT+213;g.draw3DRect(LEFT,TOP,44,35,true);LEFT=LEFT+46;//win键g.draw3DRect(LEFT,TOP,46,35,true);LEFT=LEFT+48;//快捷键g.draw3DRect(LEFT,TOP,42,35,true);LEFT=LEFT+44;//右Ctrl键g.draw3DRect(LEFT,TOP,53,35,true);//编辑键区图形绘制完成//绘制字母、符号-------LEFT=lTemp;TOP=tTemp;g.setColor(Color.lightGray);Font f=new Font("x",Font.BOLD,13);g.setFont(f);LEFT=LEFT+7;TOP=TOP+14;for(int i=1;i<=13;i++){g.drawString(shift.substring(i-1,i),LEFT,TOP);g.drawString(noShift.substring(i-1,i),LEFT,TOP+18);LEFT=LEFT+37;}f=new Font("x",Font.BOLD,12);g.setFont(f);g.drawString("BackSpace",LEFT-4,TOP+8);LEFT=lTemp+7;TOP=TOP+37;g.drawString("Tab",LEFT,TOP+8);f=new Font("x",Font.BOLD,14);g.setFont(f);LEFT=lTemp+63;for(int i=13;i<=25;i++){g.drawString(shift.substring(i,i+1),LEFT,TOP);if(i>=23)g.drawString(noShift.substring(i,i+1),LEFT,TOP+16);LEFT=LEFT+37;}f=new Font("x",Font.BOLD,12);g.setFont(f);LEFT=lTemp;TOP=TOP+37;g.drawString("CapsLock",LEFT+7,TOP+8);f=new Font("x",Font.BOLD,14);g.setFont(f);LEFT=lTemp+74;for(int i=26;i<=36;i++){g.drawString(shift.substring(i,i+1),LEFT,TOP);if(i>=35)g.drawString(noShift.substring(i,i+1),LEFT,TOP+16);if("F".equals(shift.substring(i,i+1)) || "J".equals(shift.substring(i,i+1)))g.drawString("_",LEFT+5,TOP+15);LEFT=LEFT+37;}f=new Font("x",Font.BOLD,12);g.setFont(f);g.drawString("Enter←┘",LEFT+15,TOP+8);LEFT=lTemp+7;TOP=TOP+37;g.drawString("↑Shift",LEFT,TOP+8);f=new Font("x",Font.BOLD,14);g.setFont(f);LEFT=lTemp+91;for(int i=37;i<=46;i++){g.drawString(shift.substring(i,i+1),LEFT,TOP);if(i>=44)g.drawString(noShift.substring(i,i+1),LEFT,TOP+16);LEFT=LEFT+37;}f=new Font("x",Font.BOLD,12);g.setFont(f);g.drawString("↑Shift",LEFT,TOP+8);LEFT=lTemp+7;TOP=TOP+37;g.drawString("Ctrl",LEFT,TOP+8);LEFT=LEFT+55;g.drawString("Win",LEFT,TOP+8);LEFT=LEFT+46;g.drawString("Alt",LEFT,TOP+8);LEFT=LEFT+46;g.drawString("Space",LEFT+90,TOP+8);LEFT=LEFT+213;g.drawString("Alt",LEFT,TOP+8);LEFT=LEFT+46;g.drawString("Win",LEFT,TOP+8);LEFT=LEFT+50;g.drawString("SM",LEFT,TOP+8);LEFT=LEFT+44;g.drawString("Ctrl",LEFT,TOP+8);}
@Override
public void keyTyped(KeyEvent e) {// TODO Auto-generated method stubSystem.out.print(e.getKeyChar());
}
@Override
public void keyPressed(KeyEvent e) {// TODO Auto-generated method stubSystem.out.print(e.getKeyChar());
}
@Override
public void keyReleased(KeyEvent e) {// TODO Auto-generated method stubSystem.out.print(e.getKeyChar());
}}

PublicData.java(共享数据)

public class PublicData {//共享数据、用static动态变化public static String key=" ";public static String curkey;public static String Text;public static int textTag=1;//预设好五段文字public static String getText(int i){switch(i){case 1:return "The Java programming language is robust and versatile, enabling developers to:Write software on one platform and run it on another.Create programs to run within a web browser.Develop server-side applications for online forums, stores, polls, processing HTML forms, and more.Write applications for cell phones, two-way pagers, and other consumer devices.It's no wonder the Java platform attracts so many new developers.";case 2:return "Review What You've Learned Test your Java programming knowledge with these online interactive quizzes and puzzles.Learning Paths Get a short, customized learning path, based on your programming experience.References & Resources A collection of references and resources to use for Java development.";case 3:return "Certification and Courses Links to information on taking Sun's courses and getting certified as a Java programmer, developer, or architect.The New to Java Programming Center provides instructional articles and tutorials for developing on the Java platform. ";case 4:return "Read through materials listed in the four easy-to-follow steps, or use the interactive Learning Path for a customized path, based on your programming experience. ";case 5:return "There were a sensitivity and a beauty to her that have nothing to do with looks. She was one to be listened to, whose words were so easy to take to heart.It is said that the true nature of being is veiled.";}return Text;}
}

三、程序演示

项目结构:

四、总结反思

这个程序很好的练习学习了java swing,收获最大应该是这个虚拟键盘的设计,以前对于实现这个虚拟键盘完全不知道从何做起。如果是完全没有接触过java swing的同学直接下手做项目是非常困难的,我在已经做过项目的情况下还发现Java swing有许许多多陌生和的类和方法,好的办法是先有了对基础类大致的了解下,找一个做好的项目来进行修改,不会的再单独学习某个类的使用方法,变成自己的东西。有了这些基本的框架后就可以个性化的设计自己的作品了。

仿金山打字通游戏,模拟键盘(java swing),提示输入,导入本地txt文件相关推荐

  1. 仿金山打字通游戏 Java代码

    Code: package com.mxs.util;import javax.swing.*; import java.awt.*; import java.awt.event.*;public c ...

  2. java类似金山打字的键盘模拟_Java仿金山打字通打字母游戏《Java就该这样学》

    前面我写过关于键盘控制小球,以及模仿下雪的代码.此次算是对前一段时间知识的汇总.依旧很肤浅的没有面向对象的概念.还是俩个class. MyChar 为主测试类,MyPanel为功能类.MyPanel已 ...

  3. java打字游戏_Java仿金山打字通打字母游戏《Java就该这样学》

    前面我写过关于键盘控制小球,以及模仿下雪的代码.此次算是对前一段时间知识的汇总.依旧很肤浅的没有面向对象的概念.还是俩个class. MyChar 为主测试类,MyPanel为功能类.MyPanel已 ...

  4. java数据保存到文件_Java把数据存储到本地txt文件

    码农公社  210.net.cn  210= 1024  10月24日一个重要的节日--码农(程序员)节 Java把数据存储到本地txt文件 java存储数据,方便打印日志等 1.覆盖以前的数据 tr ...

  5. java swing游戏编程高仿金山打字教程-拯救苹果

    原文:java swing游戏编程高仿金山打字教程-拯救苹果 源代码下载地址:http://www.zuidaima.com/share/1786650901515264.htm 这几天学习了一下ja ...

  6. C语言编一个金山打字通小游戏,js实现金山打字通小游戏

    本文实例为大家分享了js实现金山打字通小游戏的具体代码,供大家参考,具体内容如下 字母匀速随机下落,键盘按下对应字母按键,字母消失重新生成新字母,新字母可帮助回调一部分初始高度 效果 1.页面内容 列 ...

  7. 金山打字通2008完整版包含金山打字游戏,网上唯一的

    金山打字通2008 官方正式完整版,网上唯一的,其他都是不完整的.2007,2009版为虚假,官方未出此版. [概括介绍] 金山打字通是一款学习打字软件具有英文打字.拼音打字.五笔打字.打字游戏等功能 ...

  8. Dev-C++游戏创作之金山打字通(附带音乐)

    Hi!大家好!我是你们的编程小王子 最近一直拖着没更新,因为实在是没什么游戏思路.但是终于搞出来一个 金山打字通相信很多小伙伴们都认识,所以东西我就不多介绍,今天主要讲解音乐的播放(超级简单的)! / ...

  9. 键盘录入、提高成绩(金山打字通)

    目标:修改文章内容从而提高打字成绩. ①打开金山打字通自定义目录: c盘\AppData\Roaming\TypeEasyData\user\user1\diycourse\ (以我的安装目录为例,具 ...

最新文章

  1. dig挖出DNS的秘密
  2. Algs4-1.5.4给出id[]和sz[]的内容与次数
  3. 面试题整理5 顺时针打印矩阵
  4. 冀教版五年级计算机教学计划,冀教版五年级科学教学计划
  5. google compute test Problem 1题
  6. ActiveMQ 持久化讯息数据库信息
  7. js中报错 ajax不存在,AJAX
  8. [Android源码]Android源码之高仿飞鸽传书WIFI热点搜索与创建(一)
  9. 西昌学院计算机,西昌学院
  10. 浏览器了解(三)CSS解析
  11. mysql8.0.12不能用_使用最新版本MySQL8.0.12报错记录
  12. Hive中Database、Table的创建与查询
  13. db2 查看属性的数据类型 小数位 null约束
  14. 23模式之: 迭代器模式demo
  15. SQL Server数据同步的研究(单向/双向)
  16. 制药企业常用质量管理软件TrackWise概述
  17. 软件冒烟测试报告,冒烟测试方法及报告模板
  18. mmd 到 blender 到 ue4/ue5 缩放比例相关的处理流程
  19. 2016全球排名前50的博客网站性能
  20. Elephant Swap的LaaS方案迅速崛起,构建全新DeFi2.0协议

热门文章

  1. 解决Eclipse在线下载插件时遇到的问题
  2. 怎么压缩pdf,如何压缩pdf大小,4种高质量办法
  3. Blender图解教程:新手入门练习
  4. 什么是事务隔离级别,事务隔离级别详解
  5. 感同身受!12个数据科学家秒懂的瞬间
  6. PTA 7-97 计算个人所得税
  7. 金立手机连接wifi显示服务器,金立手机连接wifi身份验证出现问题是怎么 – 手机爱问...
  8. 教学PPT录制 ActivePresenter Pro 精简绿色版
  9. 入耳式无线蓝牙耳机哪款好?无线入耳式蓝牙耳机音质排行榜
  10. 删除QQ说说/关闭QQ空间