2014-01-12 39 views
1

我目前,为了好玩更改布尔值,使得乒乓球比赛但是我目前被困尝试通过w键按下,让我的布尔“goingup”的真实状态的值。我有我的渲染类中的布尔值,以及int x和int y,并设置为false。在这个类中,我画了一个正方形,其中x为int x,y为int y。在另一个类(Framemake.java)中,我有一个关键侦听器设置为我的Jframe。在这堂课中,我有keylistener倾听w键的按键和释放。这里是我的问题就出现了:如果W键被按下我希望它goingup更改为true,如果它的发布我希望它改变上升为false;这工作得很好,但问题是在我的呈现类我有设置一个计时器,这是然后在图形方式(不知道正确的名称)开始。在定时器执行的操作中,我已经设定:如果上升是真的,我希望它打印出“上升是真实的 - 渲染”。这是问题所在 - 即使由于按键被按下而导致上升,打印也不会被打印到屏幕上。 (三江源读这篇文章,我需要你怎么回事导通,即使它可能是也可能不是真的很明显完全理解)。爪哇 - 在一个类从另一个类

下面是代码: Starter.java

public class Starter { 

public static void main(String[] args) { 
    Frame frame = new Frame(); 
    frame.Start(); 

} 

} 

这里是Frame.java Render.java的

public class Frame implements Runnable { 
Framemake r = new Framemake(); 

public void Start(){ 
    new Thread(this).start();// 
} 
public void run() { 

    try { 
     r.framemade(); 
     } 
    catch (Exception e) { // 
     e.printStackTrace(); 
    } 

} 

    } 

这里是作为份我是有麻烦粘贴到该交

public class Render extends JPanel implements ActionListener { 

boolean goingup = false; 
boolean goingdown = false; 
int x = 0; //starting pos of x . 
int y = 150;//starting pos of y 
Timer tm = new Timer(7, this); //The timer is created 



public void paintComponent(Graphics g) { 
    Framemake frames = new Framemake(); 
    super.paintComponent(g); 
    tm.start(); 
    g.setColor(Color.GREEN); 
    g.fillRect(x, y, 20, 150); 
    g.dispose(); 
} 

public void actionPerformed(ActionEvent e){ //timer 
    if(goingup){ 
    System.out.println("Going up is true- render"); 
    x++;//for example... 
    repaint(); 
    } 
} 

这里是Framemake.java

public class Framemake implements KeyListener { 
    int WIDTH = 500; 
    int HEIGHT = 500; 
    Render c = new Render(); 
    public void framemade() { 
     System.out.println("Frame starting"); 
     //Frame is created here 
     Render render = new Render(); 
     JFrame frame = new JFrame(); 
     frame.setSize(WIDTH, HEIGHT); 
     frame.setVisible(true); 
     frame.setResizable(false); 
     frame.setLocationRelativeTo(null); 
     frame.setTitle("Animation"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     Window w = frame; 
     w.addKeyListener(this); 
     frame.add(render); //displays all graphics from render to the screen 
    } 
    public void keyPressed(KeyEvent e) { 
     int keyCode = e.getKeyCode(); 
     if (keyCode == KeyEvent.VK_W) { 
      System.out.println("Going up"); 
      c.goingup = true; 
     } 
     if (keyCode == KeyEvent.VK_S) { 
      System.out.println("Going down"); 
      c.goingdown = true; 
     } 
    } 
    public void keyReleased(KeyEvent e) { 
     int keyCode = e.getKeyCode(); 
     if (keyCode == KeyEvent.VK_W) { 
      System.out.println("Up terminated"); 
      c.goingup = false; 
     } 
     if (keyCode == KeyEvent.VK_S) { 
      System.out.println("Down terminated"); 
      c.goingdown = false; 
     } 
    } 
    public void keyTyped(KeyEvent e) {} 
} 

我希望这里的问题很明确(对不起,如果我错误地发布了我的代码),任何帮助表示赞赏。

回答

2

问题是,在您的班级Framemake中,您没有将Render c添加到frame。您正在创建一个本地变量render

为了解决这个问题,只需要删除的

Render render = new Render(); 

声明,并添加cframe

frame.add(c); // Instead of 'frame.add(render)' 

摘要:你的方法framemade()应该是这样的:

public void framemade() 
{ 
    System.out.println("Frame starting"); 
    //Frame is created here 
    JFrame frame = new JFrame(); 
    frame.setSize(WIDTH, HEIGHT); 
    frame.setVisible(true); 
    frame.setResizable(false); 
    frame.setLocationRelativeTo(null); 
    frame.setTitle("Animation"); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    Window w = frame; 
    w.addKeyListener(this); 
    frame.add(c); // Change this line 
} 

编辑:

我也建议你阅读为什么你应该使用私人领域,getter和setters。尝试thisthis

+2

+1因为我实际上错过了。这确实是问题! –

+1

谢谢大家的非常快速的回复 - 感谢它,现在完美:)。 – arunptl100

+1

@ arunptl100它看起来像你已经弄清楚了。欢迎来到StackOverflow! – Christian

0

我会想,你的计时器不火的。您应该只启动一次,而不是在paintComponent方法中。由于默认情况下,它将每7毫秒触发一次。 还添加一条线,看看是否actionPerformed方法实际上触发:

public void actionPerformed(ActionEvent e){ //timer 
    System.out.println("Timer: actionPerformed"); 
    if(goingup){ 
    System.out.println("Going up is true- render"); 
    x++;//for example... 
    repaint(); 
    } 
} 

你们为什么叫在paintComponent方法g.dispose();?每个重绘都调用此方法。这很可能会导致问题。

+0

我试过了,它没有工作计时器:actionPerformed在控制台中重复提示计时器正在运行但你说我应该在其他地方启动计时器? – arunptl100

+0

好吧。是的,在Render类的构造函数中启动它。它只需要启动一次。 –

0

您应该能够通过简单地添加这样的方法来做到这一点,然后调用: 公共无效setgoingup(布尔B){ this.goingup = B; }

PS:我累了,并没有阅读所有的代码 - 对不起,如果我错过了什么ovious。

+0

好处是,OP确实应该将属性设置为private,并调用setter或方法来执行所需的操作。但这不是他问题的根源。 –

+0

好吧,即时通讯如果我错了,抱歉,如上所述,我有点累,现在实际上会睡觉。只是以为我可以帮助一点点:P – Marenthyu

0

您需要使用observer(或通知程序)模式。

一个非常简单的(幼稚)例如: 创建一个类,将起到观察到的作用,并 接口与观察者的角色,对其实施 类一起。 保持一个列表,可观察类的观察者实例需要的时候通知,并且这样做的

(注意:未经测试的代码):

public interface Observer{ 
    public void notify(); 
} 

public class Observable{ 
    public List<Observer> _observers; 

    public Observable(){ 
    _observers = new List<Observer>(); 
    } 

    public void registerObserver(Observer obs){ 
    _observers.add(obs) 
    } 

    public void unregisterObserver(Observer obs){ 
    _observers.remove(obs); 
    } 

    public void notifyObservers{ 
    for(Observer obs : _observers) { 
     obs.notify(); 
    } 
    } 

} 

public class SpecificObserver implements Observer{ 
    //Properties, Ctors etc 

    public void notify(){ 
    //Do stuff when notified here 
    } 
} 


and in your program: 

public static void main(string[] args){ 

    Observable observable    = new Observable(); 
    SpecificObserver specificObserver = new SpecificObserver(); 
    //More init code here 

    observable.registerObserver(specificObserver); 
    //Etc... 

    //read input 
    string str = YourClass.GetInput(); 

    while(!str.Equals("EndString")) 
    { 
    if(str.Equals("SpecificInput")) 
    { 
     observable.notifyObservers(); 
    } 
    str = YourClass.GetInput(); 
    } 

} 

当然,你也可以将它修改为您的需求(为Notify方法添加参数,运行循环到另一个线程,检查你想要的条件,而不是输入等)