我想让一个小程序在我每次键入时显示一个字母,然后在我每次按下它时移动一个字母

i want to make an applet display a letter every time i type and then move over a letter every time i press it

代码如下。现在它所做的是不断移动字母,我只希望它在我按下下一个字母时移动一个字符而不是移动更多。 x+=2 也是我使用的另一种方法,它也没有用。这基本上应该是输入 class... 请 help.It 也将所有字母放在同一个地方.. 我需要它把它们分开 space 并且我不能按同一个字母两次或者它只是移动字母

public class Type_Client extends Applet implements KeyListener,Runnable
{
 boolean pickA,pickB,pickC,pickD,pickE,pickF,pickG,pickH,pickI,pickJ,pickK=false;
 boolean pickL,pickM,pickN,pickO,pickP,pickQ,pickR,pickS,pickT,pickU,pickV=false;
 boolean pickW,pickX,pickY,pickZ=false;
 boolean space=false;
 boolean run=true;
 int x=10;
 Type t1;
 Thread thr;
 public void init()
 {
     t1 = new Type();
     thr=new Thread(this);
     thr.start();
     addKeyListener(this);
 }
     public void keyTyped(KeyEvent k)
 {
 }
 public void keyReleased(KeyEvent k)
 {
 }
 public void keyPressed(KeyEvent k)
 {
     if(k.getKeyCode()==KeyEvent.VK_A)
    {
        pickA=true;
        k.consume();

    }
     if(k.getKeyCode()==KeyEvent.VK_B)
    {
        pickB=true;
        k.consume();
    }
     if(k.getKeyCode()==KeyEvent.VK_C)
    {
        pickC=true;
        k.consume();
    }

     if(k.getKeyCode()==KeyEvent.VK_SPACE)
    {
        space=true;
        k.consume();
        //Spce++;
    }
 }
  public void run()
 {
    while(run==true)
    {
        try{
            Thread.sleep(20);
        }
        catch(Exception e){};
        repaint();
    }
}
public void paint(Graphics g)
{
    if(pickA)
    {
        g.drawString(" a",x,10);

    }
    if(pickB)
    {
        g.drawString(" b",x,10);
        x++;
        x++;
    }
    if(pickC)
    {
        g.drawString(" c",x,10);
        x++;
        x++;
    }

    }
}
public void stop()
 {
 }
public void start()
{
}
}

你的代码有很多问题。


首先,无限重绘循环:

public void run() {
    while(run==true) {
        try {
            Thread.sleep(20);
        }
        catch(Exception e) { };
        repaint();
    }
}

这很糟糕。删除它和启动它的线程!

您只需要重新绘制 JFrame/JPanel/Applet 当应用程序自身的绘制方式发生变化时(或者当 window 几何形状发生变化或 window 暴露时,但工具包已经处理了所有这些案例)。

好的,什么时候会有变化?可能任何时候你按下一个键。

public void keyPressed(KeyEvent k) {
    // Your existing code here

    repaint();
}

不再是每 20 毫秒重新绘制一次,现在您只在按下一个键后才重新绘制。这可能仍然太频繁了。 ShiftAltCtrlMetaCaps Lock都是key;如果你按下其中任何一个,尽管你的应用程序没有处理任何这些键,但重绘将被触发。但至少是一个轻微的低效率。


其次,x是一个字段,而不是局部绘制变量。它在应用程序启动时初始化为 10,并在调用 paint 时递增。

g.drawString(" b",x,10);

当应用程序启动并按下 VK_B 时,将在 (10,10) 绘制字符串 " b"。但是下次调用重绘时(使用现有代码 20 毫秒后),它将在 (12,10)、(14, 10)、(16, 10) 处绘制,依此类推。

相反,您可能想要:

public void paint(Graphics g) {
    int x = 10;

    // Remainder of paint code ...
}

因此每次调用 paint 时,它都会以相同的方式绘制(除非应用程序状态发生某些变化导致绘画故意以不同方式绘制)。


drawString 使用像素坐标。在任何清晰的字体中,字母 "A" 的宽度都超过 2 像素。例如,在这个 ASCII 艺术中,字母 "A" 和 "B" 的宽度为 5 "pixels"。要在字母之间留出间隙,"B" 需要在 "A".

右侧 至少 6 像素 绘制
  *    ****
 * *   *   *
*   *  ****
*****  *   *
*   *  *   *
*   *  ****

<-7px->

您可以使用 Graphics#getFontMetrics 根据前面的字符,使用给定的字体来确定每个字符的位置前进多少。

或者,您可以使用(比如)16 像素的恒定前进。

private final static int ADVANCE = 16;

public void paint(Graphics g) {
    int x = 10;
    if (pickA) {
        g.drawString("a", x, 10);
        x += ADVANCE;
    }
    if (pickB) {
        g.drawString("b", x, 10);
        x += ADVANCE;
    }
    // ...
}

或者您可以让工具包为您完成工作,然后绘制 String

public void paint(Graphics g) {
    StringBuilder sb = new StringBuilder(27);

    if (pickA) {
        sb.append("a ");
    }
    if (pickB) {
        sb.append("b ");
    }
    // ... remainder cases ...

    g.drawString(sb.toString(), 10, 10);
}

最后,您的 26 个 pick(Letter) 变量简直糟透了。考虑一种不同的方法来记录按下了哪些键。

部分选项:

boolean picked [] = new boolean[26];     // boolean array (1 per letter)
Set<Integer> picked = new HashSet<>();   // A set of VK_ codes
Set<Character> picked = new HashSet<>(); // A set of characters
BitSet picked = new BitSet(26);          // A set of bits (1 per letter)

这是我可以为您制作的最小的工作示例。根据需要进行调整。

@SuppressWarnings("serial")
public class Type_Client extends Applet {

    private String typed = "";

    private KeyAdapter adapter = new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            char ch = e.getKeyChar();
            if (ch >= ' ' && ch <= '~') {
                typed += ch;
                repaint();
            }
        }
    };

    @Override
    public void start() {
        addKeyListener(adapter);
    }

    @Override
    public void stop() {
        removeKeyListener(adapter);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        g.drawString(typed, 10, 10);
    }
}