我想让一个小程序在我每次键入时显示一个字母,然后在我每次按下它时移动一个字母
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 毫秒重新绘制一次,现在您只在按下一个键后才重新绘制。这可能仍然太频繁了。 Shift
、Alt
、Ctrl
、Meta
、Caps 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);
}
}
代码如下。现在它所做的是不断移动字母,我只希望它在我按下下一个字母时移动一个字符而不是移动更多。 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 毫秒重新绘制一次,现在您只在按下一个键后才重新绘制。这可能仍然太频繁了。 Shift
、Alt
、Ctrl
、Meta
、Caps 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".
* ****
* * * *
* * ****
***** * *
* * * *
* * ****
<-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);
}
}