守则如下。它现在的作用是它不断地移动这封信,我只想让它移动一个字符,当我按下一个字母而不是更多。此外x + = 2是我使用的另一种方法,它也没有工作..这基本上应该是一个打字类...请帮助。它也把所有字母放在同一个地方..我需要它将它们分开一个空格,我不能按两次相同的字母,或只是移动字母
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()
{
}
}
答案 0 :(得分:0)
您的代码存在许多问题。
首先,无限重绘循环:
public void run() {
while(run==true) {
try {
Thread.sleep(20);
}
catch(Exception e) { };
repaint();
}
}
这很糟糕。删除它和启动它的线程!
当应用程序绘制自身的方式发生变化时(或者当窗口几何体发生变化或窗口暴露时,但工具包已经处理了所有这些情况),您只需要重新绘制JFrame / JPanel / Applet。
好的,那么什么时候有变化?可能只要你按一个键就可以了。
public void keyPressed(KeyEvent k) {
// Your existing code here
repaint();
}
而不是每20毫秒重新绘制一次,现在只需在按下一个键后重新绘制。这可能仍然经常发生。 Shift
,Alt
,Ctrl
,Meta
,Caps Lock
都是关键字;如果您按下其中任何一个,即使您的应用程序未处理任何这些键,也会触发重新绘制。但至少是效率低下。
其次,x
是一个字段而不是本地绘制变量。它在应用程序启动时初始化为10
,并在调用paint时递增。
g.drawString(" b",x,10);
当应用程序启动并按下" b"
时,将在(10,10)处绘制字符串VK_B
。但是下次重新调用时(使用现有代码20ms后),它将在(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"像素"宽。为了在字母之间留一个空隙," 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);
}
}