小弟是个Java新手,现打算实现一个简单的打字游戏程序。在制作过程中遇到疑难,望各路大侠帮忙给看看。
    问题:在一个面板上面使用2个线程,分别控制各自的字母下落。感觉这种思路应该可行,但奇怪的是面板中没有任何应该显示的字母。(其他绘制的线都能正常显示)。为了给花时间帮忙的朋友以方便,我在下边对程序中的个别地方做了说明。
    
    说明1:下面是我的绘图面板类中的paint方法的具体内容:
          public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2=(Graphics2D)g;

if(tf.level==5)//这里原为tf.level==0,即去执行游戏第0级的方法levelZero
{
levelZero(g2,this);
}

if(tf.level==0)//这里原为tf.level==1,即去执行游戏第1级的方法levelOne
{              //现为了解决问题的方便,将它改为0,直接从第1级开始游戏
levelOne(g2,this);
}

}
    
    说明2:以下是游戏第1级的具体方法代码
         
         boolean oneStart=false;//记录1级是否初始化开始
public void levelOne(Graphics2D g2,LetterDownJPanel ldp)//1级
{
g2.setColor(Color.BLUE);
g2.drawRect(5,5,ldp.getWidth()-10,ldp.getHeight()-15);
g2.drawLine(65,5,65,430);
g2.drawLine(125,5,125,430);
g2.drawLine(125,5,125,430);
g2.drawLine(185,5,185,430);

if(ldp.hit)
    g2.setColor(Color.YELLOW);
else
    g2.setColor(Color.RED);
g2.drawLine(0,ldp.getHeight()-18,ldp.getWidth(),ldp.getHeight()-18);

g2.setColor(Color.YELLOW);
g2.setFont(ldp.fontCool);

        if(oneStart==false)//从这里开始使用了2个线程,分别代表2个字母的下落情况。
        {
         LetterThread lt1=new LetterThread(g2,ldp,68,0,300,"f");
         LetterThread lt2=new LetterThread(g2,ldp,128,0,800,"s");
         lt1.start();
         lt2.start();
         oneStart=true;
        }   说明3:控制字母下落的线程类如下所述。我在必要的地方加入了测试语句,经测试发现上面说的
2个线程都已经正常的启动运行,字母下落其实也正常,但在面板中看不到效果。不知为何,怀疑是否是刷新的问题。
  class LetterThread extends Thread  //控制字母下落的线程类
 {
Graphics2D g2=null;
LetterDownJPanel ldp=null;
int letterX;
int letterY;
boolean letterChange=false;
int sleeptime;
String s;

LetterThread(Graphics2D g2,LetterDownJPanel ldp,int x,int y,int time,String s)
{
this.g2=g2;
this.ldp=ldp;
this.letterX=x;
this.letterY=y;
this.sleeptime=time;
this.s=s;
}


public void run()
{
while(true)
{
    this.ldp.paint(g2);//?????????????????????????
System.out.println("s="+this.s);
if(this.letterY>=450)
{
this.letterChange=true; 
this.letterY=0;

if(ldp.hit==false)  //如果字母没有被打中就落入屏幕底部
{
ldp.tf.labCool.setText("Miss!");
    ldp.tf.labScore.setText(""+(Integer.parseInt(ldp.tf.labScore.getText())-50));

    ldp.tf.pb.setValue(ldp.tf.pb.getValue()-3);
    if(Integer.parseInt(ldp.tf.labScore.getText())<-2500||ldp.tf.pb.getValue()<=0)
    {
    int jo=JOptionPane.showConfirmDialog(null,"Game Over!!","游戏结束",JOptionPane.OK_OPTION);
    if(jo==JOptionPane.OK_OPTION)
       System.exit(0);
    }
}

ldp.hit=false;   //一个字母落完后,将hit标记仍然置回false
}
else
{
if(this.letterChange)
{
    System.out.println("change letter !!");
    this.s=""+ldp.letterRandom();
    g2.drawString(this.s,this.letterX,this.letterY);
    this.letterChange=false;
}

else
{
System.out.println(this.s);
System.out.println(this.letterX);
System.out.println(this.letterY);
    g2.drawString(this.s,this.letterX,this.letterY);
}
   

try
{
Thread.sleep(this.sleeptime);
System.out.println("sleep"+sleeptime);
}
catch(Exception e1)
{
e1.printStackTrace();
}

this.letterY++;
System.out.println("y++"+this.letterY);
ldp.repaint();
ldp.tf.repaint();//窗体重绘,刷新整个窗体,保证每次都能看到面板上面的
                  //图像变化

}
}

}
}我在下一楼中放上全部代码,有些乱,恳请高手帮忙给瞅瞅。

解决方案 »

  1.   

    到目前为止的整个java程序代码如下:                   /********************************
                        *                              *
                        *          打字游戏            *
                        *                              *
                        ********************************/
    //打字游戏的基本功能实现.import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.JProgressBar;
    import javax.swing.JLabel;
    import java.awt.Color;
    import java.awt.BorderLayout;
    import java.awt.GridLayout;
    import java.awt.Font;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.event.KeyEvent;
    import java.awt.event.KeyListener;
    import java.lang.Thread;
    import java.util.EventListener;
    import javax.swing.JOptionPane;
    import javax.swing.JComponent;
    import java.lang.Thread;
    import java.lang.Runnable;
                        
    class TWFrame extends JFrame implements KeyListener
    {
    JProgressBar pb=new JProgressBar(0,100);
    JPanel pl=new JPanel();
    LetterDownJPanel ldp=new LetterDownJPanel(this);
    JPanel plRight=new JPanel();
    JPanel plRup=new JPanel();
    JPanel plRdown=new JPanel(); 
    JPanel plLevel=new JPanel();

    JLabel labScore=new JLabel("0");
    JLabel labCool=new JLabel("");
    JLabel labLevelNumber=new JLabel("0",JLabel.RIGHT);
    JLabel labLevel=new JLabel("级",JLabel.LEFT);

    Font fontScore=new Font("宋体",Font.BOLD,70);
    Font fontCool=new Font("华文彩云",Font.BOLD,70);
    Font fontCoolmin=new Font("华文彩云",Font.BOLD,60);
    Font fontLevel=new Font("华文行楷",Font.BOLD,40);

    int level=0;//级别

    TWFrame()
    {
    this.setBounds(180,180,500,450);
    this.setTitle("六指盘魔   打字游戏");
    this.setLayout(new BorderLayout());
    this.add(pb,BorderLayout.SOUTH);
    pb.setForeground(Color.RED);
    pb.setValue(100);
    pb.setStringPainted(true);

    this.add(pl);
    pl.setLayout(new GridLayout(1,2));
    pl.add(ldp);
    ldp.setBackground(Color.BLACK);
    pl.add(plRight);

    plRight.setLayout(new GridLayout(5,1));
    plRight.add(plRup);
    plRight.add(plRdown);
    plRight.add(plLevel);


    plRup.add(labScore);
    labScore.setForeground(Color.BLUE);
    labScore.setFont(fontScore);
    plRdown.add(labCool);
    labCool.setFont(fontCool);
    labCool.setForeground(Color.RED);
    plLevel.add(labLevelNumber);
    plLevel.add(labLevel);
    plLevel.setBackground(Color.BLACK);
    labLevelNumber.setFont(fontLevel);
    labLevelNumber.setForeground(Color.GREEN);
    labLevel.setFont(fontLevel);
    labLevel.setForeground(Color.GREEN);

    this.addKeyListener(this);

    this.setResizable(false);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setVisible(true);

    }

    public void keyTyped(KeyEvent e) 
    {
    System.out.println(e.getKeyChar());


    if((""+e.getKeyChar()).equals(ldp.s)&&ldp.letterY>=355&&ldp.letterY<=400)
    {
    this.labCool.setText("Cool!");
    this.labScore.setText(""+(Integer.parseInt(this.labScore.getText())+100));
    ldp.hit=true;
    ldp.s="";//打中就让字母消失

    if(Integer.parseInt(this.labScore.getText())==1500)
    {
    this.level=1;
    this.labLevelNumber.setText("1");

    }
    }
    else
    {
    this.labCool.setText("Miss!");
    this.labScore.setText(""+(Integer.parseInt(this.labScore.getText())-50));

    this.pb.setValue(this.pb.getValue()-3);
    if(Integer.parseInt(this.labScore.getText())<-2500||this.pb.getValue()<=0)
    {
    int jo=JOptionPane.showConfirmDialog(null,"Game Over!!","游戏结束",JOptionPane.OK_OPTION);
    if(jo==JOptionPane.OK_OPTION)
       System.exit(0);
    }
    }
    } public void keyPressed(KeyEvent e){}
    public void keyReleased(KeyEvent e){}
    }
      

  2.   

    接上面class LetterDownJPanel extends JPanel
    {
    Font fontCool=new Font("宋体",Font.BOLD|Font.ITALIC,70);
    int letterX=100;
    int letterY=0;
    boolean letterChange=false;  //是否变换新的字母
    boolean hit=false;           //是否打中字母
    String s="f";                //初始时显示的字母为F

    TWFrame tf=null;

    LetterDownJPanel(TWFrame tf)
    {
    this.tf=tf;
    }

    public void paint(Graphics g)
    {
    super.paint(g);
    Graphics2D g2=(Graphics2D)g;

    if(tf.level==5)
    {
    levelZero(g2,this);
    }

    if(tf.level==0)
    {
    levelOne(g2,this);
    }

    }

    public char letterRandom() //产生随机字母的方法
    {
    int r;
        r=(int)(Math.random()*26+1);

        char c=(char)('a'+r);
        return(c);
    }

    public void levelZero(Graphics2D g2,LetterDownJPanel ldp)//0级
    {
    g2.setColor(Color.BLUE);
    g2.drawRect(5,5,ldp.getWidth()-10,ldp.getHeight()-15);
    g2.drawLine(90,5,90,430);
    g2.drawLine(150,5,150,430);

    if(ldp.hit)
        g2.setColor(Color.YELLOW);
    else
        g2.setColor(Color.RED);
    g2.drawLine(0,ldp.getHeight()-18,ldp.getWidth(),ldp.getHeight()-18);

    g2.setColor(Color.YELLOW);
    g2.setFont(ldp.fontCool);

    if(ldp.letterY>=450)
    {
    ldp.letterChange=true; 
    ldp.letterY=0; if(ldp.hit==false)  //如果字母没有被打中就落入屏幕底部
    {
    ldp.tf.labCool.setText("Miss!");
        ldp.tf.labScore.setText(""+(Integer.parseInt(ldp.tf.labScore.getText())-50));

        ldp.tf.pb.setValue(ldp.tf.pb.getValue()-3);
        if(Integer.parseInt(ldp.tf.labScore.getText())<-2500||ldp.tf.pb.getValue()<=0)
        {
        int jo=JOptionPane.showConfirmDialog(null,"Game Over!!","游戏结束",JOptionPane.OK_OPTION);
        if(jo==JOptionPane.OK_OPTION)
           System.exit(0);
        }
    }

    ldp.hit=false;   //一个字母落完后,将hit标记仍然置回false
    }
    else
    {
    if(ldp.letterChange)
    {
        ldp.s=""+this.letterRandom();
        g2.drawString(ldp.s,ldp.letterX,ldp.letterY);
        ldp.letterChange=false;
    }

    else
        g2.drawString(ldp.s,ldp.letterX,ldp.letterY);    

    try
    {
    Thread.sleep(5);
    }
    catch(Exception e1)
    {
    e1.printStackTrace();
    }

    ldp.letterY++;
    ldp.repaint();
    ldp.tf.repaint();//窗体重绘,刷新整个窗体,保证每次都能看到面板上面的
                      //图像变化
    }
    }
    boolean oneStart=false;//记录1级是否初始化开始
    public void levelOne(Graphics2D g2,LetterDownJPanel ldp)//1级
    {
    g2.setColor(Color.BLUE);
    g2.drawRect(5,5,ldp.getWidth()-10,ldp.getHeight()-15);
    g2.drawLine(65,5,65,430);
    g2.drawLine(125,5,125,430);
    g2.drawLine(125,5,125,430);
    g2.drawLine(185,5,185,430);

    if(ldp.hit)
        g2.setColor(Color.YELLOW);
    else
        g2.setColor(Color.RED);
    g2.drawLine(0,ldp.getHeight()-18,ldp.getWidth(),ldp.getHeight()-18);

    g2.setColor(Color.YELLOW);
    g2.setFont(ldp.fontCool);

            if(oneStart==false)
            {
             LetterThread lt1=new LetterThread(g2,ldp,68,0,300,"f");
             LetterThread lt2=new LetterThread(g2,ldp,128,0,800,"s");
             lt1.start();
             lt2.start();
             oneStart=true;
            }

    }
    }
      

  3.   

    接上面(1)class LetterThread extends Thread  //控制字母下落的线程类
    {
    Graphics2D g2=null;
    LetterDownJPanel ldp=null;
    int letterX;
    int letterY;
    boolean letterChange=false;
    int sleeptime;
    String s;

    LetterThread(Graphics2D g2,LetterDownJPanel ldp,int x,int y,int time,String s)
    {
    this.g2=g2;
    this.ldp=ldp;
    this.letterX=x;
    this.letterY=y;
    this.sleeptime=time;
    this.s=s;
    }


    public void run()
    {
    while(true)
    {
        this.ldp.paint(g2);//?????????????????????????
    System.out.println("s="+this.s);
    if(this.letterY>=450)
    {
    this.letterChange=true; 
    this.letterY=0;

    if(ldp.hit==false)  //如果字母没有被打中就落入屏幕底部
    {
    ldp.tf.labCool.setText("Miss!");
        ldp.tf.labScore.setText(""+(Integer.parseInt(ldp.tf.labScore.getText())-50));

        ldp.tf.pb.setValue(ldp.tf.pb.getValue()-3);
        if(Integer.parseInt(ldp.tf.labScore.getText())<-2500||ldp.tf.pb.getValue()<=0)
        {
        int jo=JOptionPane.showConfirmDialog(null,"Game Over!!","游戏结束",JOptionPane.OK_OPTION);
        if(jo==JOptionPane.OK_OPTION)
           System.exit(0);
        }
    }

    ldp.hit=false;   //一个字母落完后,将hit标记仍然置回false
    }
    else
    {
    if(this.letterChange)
    {
        System.out.println("change letter !!");
        this.s=""+ldp.letterRandom();
        g2.drawString(this.s,this.letterX,this.letterY);
        this.letterChange=false;
    }

    else
    {
    System.out.println(this.s);
    System.out.println(this.letterX);
    System.out.println(this.letterY);
        g2.drawString(this.s,this.letterX,this.letterY);
    }
       

    try
    {
    Thread.sleep(this.sleeptime);
    System.out.println("sleep"+sleeptime);
    }
    catch(Exception e1)
    {
    e1.printStackTrace();
    }

    this.letterY++;
    System.out.println("y++"+this.letterY);
    ldp.repaint();
    ldp.tf.repaint();//窗体重绘,刷新整个窗体,保证每次都能看到面板上面的
                      //图像变化

    }
    }

    }
    }class Test
    {
    public static void main(String[] args)
    {
    JFrame.setDefaultLookAndFeelDecorated(true);
    new TWFrame();
    }
    }
    //代码结束
      

  4.   

    这种事情在Win32编程上是不敢想想的,不知道Java会怎么样。
    第一,从线程的角度来讲,这么做的了,你要同步和互斥。
    第二,从设计的角度看,最好画图的部分是MVC模式的,而文档到视图的部分,应该在一个线程内操作,这样也简单。