为什么我创造的点不移动?

时间:2017-01-05 13:12:58

标签: java swing awt

我正试图按左右键移动一个点。 这是我的主要内容:

import javax.swing.JFrame;

public class Main {

public static void main(String[] args) {

    JFrame frame = new JFrame();
    frame.setVisible(true);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setLayout(null);
    frame.setSize(500,500);
    Graphic graphic=new Graphic();
    frame.add(graphic);

}}

这是我创建点的图形类,我实现了KeyListener和ActionListener:

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.swing.JPanel;
import javax.swing.Timer;

public class Graphic extends JPanel implements ActionListener, KeyListener {
private int posX = 220;
private int posY = 300;
private Timer timer;
private int delay = 8;
private int width = 500;
private int height = 500;

public Graphic() {
    addKeyListener(this);
    setFocusable(true);
    setFocusTraversalKeysEnabled(false);
    timer = new Timer(delay, this);
    timer.start();
    this.setSize(width, height);
}

public void paint(Graphics g) {
    g.setColor(Color.black);
    g.fillRect(0, 0, width, height);

    g.setColor(Color.GREEN);
    g.fillOval(posX, posY, 20, 20);
}

@Override
public void keyPressed(KeyEvent e) {
    if (e.getKeyCode() == KeyEvent.VK_LEFT) {

        if (posX <= 20) {
            posX = 20;
        } else {
            moveLeft();

        }
    }
    if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
        if (posX >= 460) {
            posX = 460;
        } else {
            moveRight();
        }
    }
    repaint();

}

private void moveRight() {
    posX += 20;

}

private void moveLeft() {
    posX -= 20;

}

@Override
public void actionPerformed(ActionEvent e) {
    timer.start();
    repaint();

}

@Override
public void keyReleased(KeyEvent e) {
}

@Override
public void keyTyped(KeyEvent e) {
}

}

在我看来,这应该有用......但事实并非如此。当我按下左右键时没有任何反应,看起来它并没有“听”我的命令。那么,我的代码出了什么问题?

2 个答案:

答案 0 :(得分:1)

如果具有侦听器的组件具有焦点,则

BEGIN /*PREPARE SAMPLE DATA*/ CREATE TABLE #priceSchedules( RoomId int not null, [Date] date not null, Quota int not null, Price decimal(18,4) not null ) INSERT INTO #priceSchedules select RoomId = R.RoomId ,[Date] = D.[Date] ,Quota = abs(checksum(NewId()) % 5) ,Price = abs(checksum(NewId()) % 50) from ( select top 100 RoomId = row_number() over(order by R.number) from master..spt_values R ) R OUTER apply( select top 60 [Date] = cast(DATEADD(day, row_number() over(order by t1.number), getdate()) as date) from master..spt_values t1 ) D END BEGIN /*PARAMETERS*/ DECLARE @RoomId int = 5, @CheckIn date = cast(dateadd(day, 3, getdate()) as date), @CheckOut date = cast(dateadd(day, 6, getdate()) as date); DECLARE @TotalNight int = datediff(day, @CheckIn, @CheckOut) END BEGIN /*QUERY */ DBCC DROPCLEANBUFFERS WITH NO_INFOMSGS; SET STATISTICS TIME ON; --FOR CHECK PERFORMANCE PRINT('-----------START SELECT---------------------------------') SELECT * FROM ( SELECT _P.* ,RowNo = ROW_NUMBER() OVER(PARTITION BY RoomId ORDER BY DayDiffFromCheckIn) FROM( SELECT P.RoomId ,StartDate = P.[Date] ,EndDate = MAX(P2.[Date]) ,CalcDay = COUNT(*) ,DayDiffFromCheckIn = CAST(ABS(DATEDIFF(day,P.[Date],@CheckIn)) AS INT) ,MinQuota = IIF(MIN(P.Quota) > MIN(P2.Quota) ,MIN(P2.Quota),MIN(P.Quota)) ,TotalPrice = MIN(P.Price) + SUM(P2.Price) FROM #priceSchedules P JOIN #priceSchedules AS P2 ON P2.RoomId = P.RoomId AND P2.[Date] > P.[Date] AND P2.[Date] < DATEADD(day, @TotalNight ,P.[Date]) AND P2.Quota > 0 WHERE P.RoomId = @RoomId AND P.Quota > 0 AND P.[Date] >= GETDATE() GROUP BY P.RoomId,P.[Date] HAVING(COUNT(*) = (@TotalNight) - 1) -- -1 is for first row ) _P )__P WHERE __P.RowNo < 3 -- for top 3 option colsest to @CheckIn date PRINT('-----------END SELECT---------------------------------') --SELECT * FROM #priceSchedules DROP TABLE #priceSchedules SET STATISTICS TIME OFF; END 有效。
当您显示JFrame时,JFrame默认为焦点而不是JPanel。

KeyListener构造函数中,只需添加Graphic

grabFocus()

修改

我已在我的机器上测试过了。问题是它是随机工作的,因为如果我们希望JPanel抓住焦点,JFrame需要可见。有时它是,有时则不是。
public Graphic() { addKeyListener(this); setFocusTraversalKeysEnabled(true); setFocusable(true); grabFocus(); timer = new Timer(delay, this); timer.start(); this.setSize(width, height); } 可以解决问题。

将面板添加到SwingUtilities.invokeLater()后,调用以JFrame方法抓取焦点的代码。

invokeLater()

答案 1 :(得分:0)

您拨打repaint课程的Component方法,而不是paint方法。