2013-05-15 2 views
2

Делаю тетрис в Java и хотел бы иметь игру на левой и озвучивания, кнопки и nextPiece справа, как так:передачи данных между JPanel,

enter image description here

You» ll заметим, что оценка на игровой панели обновляется, но оценка на панели оценки (справа) - нет.

На панели игры, у меня есть глобальные переменные для очков и уровня: private int level, totalScore; которые инициализируются в 0.

и это в моем paint component():

 g.setColor(Color.RED); 
     g.drawString("Level: " + level, this.getWidth()/2+110, this.getHeight()/2-200); 
     g.drawString("Score: " + totalScore, this.getWidth()/2+110, this.getHeight()/2-170); 

Тогда у меня есть этот код в панели Game который вычисляет уровень и счет:

public void changeLevel() { 
    int max = (level+1)*100; 
    if (totalScore >= max) { 
     System.out.println(max + "reached... next level"); 
     level++; 
     totalScore = 0; 
     timer(); 
    } 
} 

public int tallyScore(int totalLines) { 
    int score = 0; 
    switch (totalLines) { 
     case 1: score = 40 * (level + 1); 
       break; 
     case 2: score = 100 * (level + 1); 
       break; 
     case 3: score = 300 * (level + 1); 
       break; 
     case 4: score = 1200 * (level + 1); 
       break; 
     default: break; 
    } 
    return score; 
} 

//loop through all rows starting at bottom (12 rows) 
public void checkBottomFull() { 
    int lines = 0; 
    for(int row = totalRows-1; row > 0; row--) { 
     while (isFull(row)) {  
      lines++; 
      clearRow(row); 
     } 
    } 
    totalScore += tallyScore(lines);  
    //check if level needs to be changed based on current score... 
    changeLevel(); 
    //reset lines after score has been incremented 
    lines=0; 
} 

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

public int getScore() { 
    return totalScore; 
} 
public int getLevel() { 
    return level; 
} 

В моем Score панели paintComponent() У меня есть board.getLevel() и board.getScore() (board класса игровой панель), так что я могу кормить оценки игровой панели на панель Score.

g.setColor(Color.BLACK); 
    g.drawString("Level: " + board.getLevel(), this.getWidth()/2, this.getHeight()/2-130); 
    g.drawString("Score: " + board.getScore(), this.getWidth()/2, this.getHeight()/2-100); 

Однако, как вы можете видеть на картинке, эти баллы не обновляются.

Любые мысли?

Спасибо!

+0

похоже, что вы делаете свою жизнь труднее, чем должно быть.вместо того, чтобы возиться с глобальными переменными, вы можете использовать интерфейс-слушатель. – desperateCoder

+1

Для лучшей помощи раньше, отправьте .. О, зачем беспокоиться? В прошлый раз ты проигнорировал меня. Я просто проголосую, чтобы закрыть. –

+0

@AndrewThompson Я не проигнорировал вас ... Я опубликовал SSCCE, но не сделал этого совершенно правильно ... Может быть, я не знаю, как публиковать SSCCE даже после прочтения того, что вы связали для меня. – Growler

ответ

4

Вы захотите разделить проблемы, чтобы их можно было разделить. Подумайте о создании класса для логики и данных, лежащих в основе вашего графического интерфейса, и скажите, что вы называете этот класс классом модели. Затем вы можете дать ему уровень и поле оценки и сделать их «связанными свойствами», что означает, что другие классы могут прослушивать изменения этих полей. Обычно я делаю это, предоставляя объект Model SwingPropertyChangeSupport и передавая его addPropertyChangeListener(PropertyChangeListener listener) и removePropertyChangeListener(PropertyChangeListener listener), а затем уведомляю все зарегистрированные изменения PropertyChangeListener, вызвав пожар PropertyChangeSupport. например,

import java.beans.PropertyChangeListener; 
import javax.swing.event.SwingPropertyChangeSupport; 

public class Model { 
    public static final String SCORE = "score"; 
    public static final String LEVEL = "level"; 
    private SwingPropertyChangeSupport pcSupport = 
     new SwingPropertyChangeSupport(this); 
    private int score; 
    private int level; 

    public void addPropertyChangeListener(PropertyChangeListener listener) { 
     pcSupport.addPropertyChangeListener(listener); 
    } 

    public void removePropertyChangeListener(PropertyChangeListener listener) { 
     pcSupport.removePropertyChangeListener(listener); 
    } 

    public int getScore() { 
     return score; 
    } 

    public void setScore(int score) { 
     int oldValue = this.score; 
     int newValue = score; 

     this.score = score; 
     pcSupport.firePropertyChange(SCORE, oldValue, newValue); 
    } 

    public int getLevel() { 
     return level; 
    } 

    public void setLevel(int level) { 
     int oldValue = this.level; 
     int newValue = level; 

     this.level = level; 
     pcSupport.firePropertyChange(LEVEL, oldValue, newValue); 
    } 

} 

Тогда любой графический интерфейс или вид компонента, который хочет, чтобы прослушать изменения значений, могут сделать это. Ниже класс сочетает в себе «View» с «Control», если вы изучаете MVC структуру:

import java.awt.FlowLayout; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.*; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 

public class UseModelGui { 

    private static void createAndShowGui() { 
     Panel1 panel1 = new Panel1(); 
     Panel2 panel2 = new Panel2(); 
     Model model = new Model(); 

     panel1.setModel(model); 
     panel2.setModel(model); 

     JFrame frame = new JFrame("UseModelGui"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().setLayout(new FlowLayout()); 
     frame.getContentPane().add(panel1); 
     frame.getContentPane().add(panel2); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 
} 

class Panel1 extends JPanel { 
    private JTextField scoreField = new JTextField(2); 
    private JTextField levelField = new JTextField(2); 

    public Panel1() { 
     scoreField.setFocusable(false); 
     scoreField.setEditable(false); 
     levelField.setFocusable(false); 
     levelField.setEditable(false); 

     add(new JLabel("score:")); 
     add(scoreField); 
     add(new JLabel("Level:")); 
     add(levelField); 
     setBorder(BorderFactory.createTitledBorder("Check Values")); 
    } 

    public void setModel(Model model) { 
     model.addPropertyChangeListener(new PropertyChangeListener() { 

     @Override 
     public void propertyChange(PropertyChangeEvent pcEvt) { 
      if (Model.LEVEL.equals(pcEvt.getPropertyName())) { 
       String level = pcEvt.getNewValue().toString(); 
       levelField.setText(level); 
      } else if (Model.SCORE.equals(pcEvt.getPropertyName())) { 
       String score = pcEvt.getNewValue().toString(); 
       scoreField.setText(score); 
      } 

     } 
     }); 
    } 

} 

class Panel2 extends JPanel { 
    private JSpinner scoreSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 
     20, 1)); 
    private JSpinner levelSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 
     10, 1)); 
    private Model model; 

    public Panel2() { 
     add(new JLabel("score:")); 
     add(scoreSpinner); 
     add(new JLabel("Level:")); 
     add(levelSpinner); 
     setBorder(BorderFactory.createTitledBorder("Set Values")); 

     scoreSpinner.addChangeListener(new ChangeListener() { 

     @Override 
     public void stateChanged(ChangeEvent evt) { 
      int score = ((Integer) scoreSpinner.getValue()).intValue(); 
      if (model != null) { 
       model.setScore(score); 
      } 
     } 
     }); 
     levelSpinner.addChangeListener(new ChangeListener() { 

     @Override 
     public void stateChanged(ChangeEvent evt) { 
      int level = ((Integer) levelSpinner.getValue()).intValue(); 
      if (model != null) { 
       model.setLevel(level); 
      } 
     } 
     }); 
    } 

    public void setModel(Model model) { 
     this.model = model; 
    } 

} 

Красота этого является то, что Panel1 не имеет никакого знания panel2, и модель не имеет никакого знания ни. Вся Panel1 знает, изменилась ли модель. Все Panel2 знает, что он меняет состояние модели. Все модели знают, что его состояние может измениться, и его значения можно прослушать.

Вы правы, что в этом простом примере это слишком много, но как только вы начинаете создавать сложные данные и состояние, это имеет смысл и становится весьма полезным.

+0

Человек, который сложный. Мне нужно начать с модели MVC по меньшему проекту, я думаю, потому что для меня здесь не совсем понятно. Но спасибо, хотя! Кроме того, вы знаете, почему, если я попытаюсь отобразить уровень и оценку с Game Panel, где находится панель оценки, она не будет отображаться? Например, добавьте 200 к местоположению по оси x, 'g.drawString (« Уровень: »+ уровень, this.getWidth()/2 + 200, this.getHeight()/2-200);' так что это будет где местоположение панели оценки ... это потому, что панель оценки перекрывает панель игры? – Growler

+2

@ Growler извините, что это немного над-убить, но как только ваше состояние становится сложным, оно может быть весьма полезным. Например, если вы выполняете программу Tetris, тогда модель будет содержать логическое состояние всех частей, включая часть, которая падает, и графический интерфейс будет слушать модель и отображать изменения в частях на чертеже. –

+0

@ Growler, потому что ScorePanel, вероятно, покрывает GamePanel, а ScorePanel непрозрачен. –

3

Вы должны отделить свою бизнес-логику от своей презентации. Пожалуйста, прочитайте о: Model View Controller узор.

+2

Возможно, это комментарий. – mre

+1

Комментарии для запроса уточнений у автора или оставляющих конструктивную критику, которые помогут автору улучшить сообщение. Я считаю, что это ответ. ;) – rebeliagamer

+0

Я считаю, что это хороший ответ и отличный комментарий; просто пытаясь помочь. :] – mre