2014-01-12 4 views
1

В настоящее время я для развлечения создаю игру для понга, но в настоящее время я застреваю, пытаясь получить значение моего булевского «подъема» в истинное состояние с помощью нажатия клавиши w , У меня есть boolean, поднимающийся в моем классе рендеринга, а также int x и int y, и установлено значение false. В этом классе я рисую квадрат, с x как int x и y как int y. В другом классе (Framemake.java) у меня есть ключевой прослушиватель, установленный для моего Jframe. В этом классе я слушаю keylistener для нажатия клавиши w и отпускания. Здесь возникает моя проблема: если нажата клавиша W, я хочу, чтобы она меняла ход на true, и, если ее освободить, я хочу, чтобы она изменилась, переместившись на false; это работает нормально, но проблема в моем классе рендеринга У меня есть настройка таймера, после чего он запускается в графическом методе (не уверен в правильном имени). В действиях таймеров, которые я выполнил, я установил: если значение true, я хочу, чтобы оно было распечатано, «go up is true-render». Вот проблема: даже если движение вверх истинно из-за нажатия клавиши w, печать не выводится на экран. (Спасибо, что прочитали это, мне нужно было полностью понять, что происходит, даже если это может быть или не быть действительно очевидным).Java - изменение логического значения в одном классе из другого класса

Вот код: Starter.java

public class Starter { 

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

} 

} 

Здесь Frame.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(); 
    } 

} 

    } 

Здесь вы Render.java части, как я имел проблемы вставки в этот пост

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(); 

и добавить c к frame:

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 
} 

Редактировать:

Я бы также рекомендовал вам прочитать, почему вы должны использовать частные поля, геттеры и сеттеры. Попробуйте this и this.

+2

+1, так как я действительно пропустил это. Это действительно проблема! –

+1

Wow thankyou все за очень быстрые ответы - Спасибо за это, он отлично работает сейчас :). – 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(); 
    } 
} 

А почему вы называете g.dispose(); в методе paintComponent? Этот метод называется для каждой перекраски. Это, скорее всего, также приведет к проблемам.

+0

Я пробовал, чтобы это и работало. Таймер: в консоли было повторено действие. вы сказали, что я должен запустить таймер в другом месте? – arunptl100

+0

Хорошо хорошо. Дайте его в конструкторе класса Render. Его нужно только запустить. –

0

Вы должны сделать это, просто добавив метод, подобный этому, и затем назовите это: Public void setgoingup (boolean b) { this.goingup = b; }

Пс: Я устал и не читал весь код - извините, если я пропустил что-нибудь острое.

+0

Хорошая точка, OP действительно должен сделать атрибут приватным и вызвать сеттер или метод, который делает нужную вещь. Но это не корень его проблем. –

+0

Хорошо, им жаль, если я ошибаюсь, как я сказал выше, я немного устал и на самом деле пойду спать. Просто подумал, что могу немного помочь: P – Marenthyu

0

Вам необходимо использовать шаблон (или уведомитель).

очень простой (и наивный) пример: Создать класс, который будет играть роль наблюдаемого, и интерфейс с ролью наблюдателя, наряду с его классами реализации . Держите список наблюдаемого класса экземпляров наблюдателей сообщить, когда это необходимо, и сделать это таким образом

(ВНИМАНИЕ: непроверенный код):

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, запустите цикл в другой поток, который проверяет условие, которое вы хотите, а не на вход и т. д.)

Смежные вопросы