2012-09-13 26 views
5

Aynı pakette iki sınıf var. Bir sınıfta static variable bildirdim ve bu değişkene başka bir sınıfta erişmek istiyorum. İşte Başka bir sınıftan statik değişkene erişme

i

public class Game { 

    private wampusGUI gui; 

    public Game(wampusGUI w) { 
     world = new World(); 
     world.start(); 
     gui = w; 
    } 

    public void play() { 
     gui.setTextArea(welcome()); 
     gui.setTextArea(describe()); 
     for (;;) { 
      String s = userCommand; // here value should come should 
      System.out.println(userCommand); 
      Command c = Command.create(s); 
      String r = c.perform(world); 
      // is game over? 
      if (r == null) { 
       break; 
      } 
      System.out.println(r); 
     } 
     System.out.println("Game over"); 
    } 
} 

Ancak değişken erişmek istediğiniz kodudur statik değişkeni İşte

public class wampusGUI extends javax.swing.JFrame { 

    static String userCommand; 

    public wampusGUI() { 
     initComponents(); 
    } 

    public void setTextArea(String text) { 
     displayTextArea.append(text); 
    } 

    private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) { 
     userCommand = commandText.getText(); 
    } 

    public static void main(String args[]) { 
     /* Create and display the form */ 
     java.awt.EventQueue.invokeLater(new Runnable() { 

      public void run() { 
       wampusGUI w = new wampusGUI(); 
       w.setVisible(true); 
       Game g = new Game(w); 
       g.play(); 
      } 
     }); 
    } 
} 

beyan eden benim kodudur i ilk gelen değişken geçirebilirsiniz argüman olarak sınıf. ama problem şu ki, program çalıştıracağım zaman değer ilk defa boşa gitmeyecek. textfield'da değeri girdiğimde istiyorum, o zaman başka bir sınıfa gitmeli.

Teşekkür ederiz. Bunun iyi bir çözüm olmadığını Jon Skeet katılıyorum

+7

"Değer null ilk defa" ile ne demek istiyorsunuz? Temel olarak tasarımınızı değiştirmelisiniz - global bir değişkene sahip olmak gerçekten iyi bir çözüm değil *. –

+1

@jon ile aynı fikirdeyim. Dize'niz, kullanıcının bunu değiştirme şansı elde edene kadar iyi bir değeri olmayacaktır. Ayrıca döngü için sonsuza dek bir Swing uygulaması için iyi bir tasarım değil. Bunun yerine, kullanıcının bir JTextField'ın durumunu değiştirip dinlemesini dinleyen bir dinleyici kullanmak isteyip istemediğinizi merak ediyorum. Belki de, programınız ve yapması gerekenler hakkında daha fazla şey öğrenene kadar, bilmeniz zor olan bir Swing Timer kullanmak isteyeceksiniz. –

+0

Lütfen bize söyleyin: Bu kodla ne yapmaya çalışıyorsunuz? –

cevap

2

Oyun nesnesinin GUI nesnesinin durumundaki değişiklikleri dinlemesine ve yanıtlamasına izin vermek için bir sıralama veya başka bir dinleyici kullanmanız önerilir. Bunu yapmanın birkaç yolu vardır, ancak bulduğum en zarif ve kullanışlı özellik, PropertyChangeListeners'ı kullanmanıza izin vermek için Swing'in kendi doğal PropertyChangeSupport'unu kullanmaktır. Tüm Swing bileşenleri ona bir PropertyChangeListener eklemenize izin verir.Ve bu yüzden sen Oyun şöyle (büyük harfle olmalıdır) sizin WampusGUI sınıfına nesne tane ekleyin sahip olduğunu, bunu öneririz: Bu Oyun gui'nin durumundaki değişiklikleri dinlemek sağlayacak

public Game(WampusGUI w) { 
    gui = w; 

    gui.addPropertyChangeListener(new PropertyChangeListener() { 
    // .... 
    } 

.

Daha sonra gui'nin userCommand Dizesini bir "sınır özelliği" haline getirmek istersiniz; bu, değiştirmeyi tüm dinleyicilere bildiren özellik değişikliği desteğini tetikleyecek bir belirleyici yöntem anlamına gelir. Ben şöyle yapardı:

private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) { 
    setUserCommand(commandText.getText()); 
} 

sonra şöyle yanıt vereceğini Oyun mülkiyet değişikliği dinleyici:

gui.addPropertyChangeListener(new PropertyChangeListener() { 

    @Override 
    public void propertyChange(PropertyChangeEvent pcEvt) { 

     // is the property being changed the one we're interested in? 
     if (WampusGUI.USER_COMMAND.equals(pcEvt.getPropertyName())) { 

      // get user command: 
      String userCommand = pcEvt.getNewValue().toString(); 

      // then we can do with it what we want 
      play(userCommand); 

     } 

    } 
    }); 

public class WampusGUI extends JFrame { 
    public static final String USER_COMMAND = "user command"; 
    // .... 

    private void setUserCommand(String userCommand) { 
     String oldValue = this.userCommand; 
     String newValue = userCommand; 
     this.userCommand = userCommand; 
     firePropertyChange(USER_COMMAND, oldValue, newValue); 
    } 

Sonra sadece bu ayarlayıcı yöntemi ile bu dize değerini değiştirecek

Bu tekniğin güzelliklerinden biri, gözlemlenen sınıfın (GUI) gözlemci sınıfı (Oyun) hakkında herhangi bir bilgisi olmamasıdır. Bunun küçük bir uygulanabilir örneği:

import java.awt.BorderLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.beans.PropertyChangeEvent; 
import java.beans.PropertyChangeListener; 

import javax.swing.*; 

public class WampusGUI extends JFrame { 
    public static final String USER_COMMAND = "user command"; 
    private String userCommand; 
    private JTextArea displayTextArea = new JTextArea(10, 30); 
    private JTextField commandText = new JTextField(10); 

    public WampusGUI() { 
     initComponents(); 
    } 

    private void setUserCommand(String userCommand) { 
     String oldValue = this.userCommand; 
     String newValue = userCommand; 
     this.userCommand = userCommand; 
     firePropertyChange(USER_COMMAND, oldValue, newValue); 
    } 

    private void initComponents() { 
     displayTextArea.setEditable(false); 
     displayTextArea.setFocusable(false); 
     JButton enterButton = new JButton("Enter Command"); 
     enterButton.addActionListener(new ActionListener() { 

     @Override 
     public void actionPerformed(ActionEvent evt) { 
      enterButtonActionPerformed(evt); 
     } 
     }); 
     JPanel commandPanel = new JPanel(); 
     commandPanel.add(commandText); 
     commandPanel.add(Box.createHorizontalStrut(15)); 
     commandPanel.add(enterButton); 

     JPanel mainPanel = new JPanel(); 
     mainPanel.setLayout(new BorderLayout()); 
     mainPanel.add(new JScrollPane(displayTextArea)); 
     mainPanel.add(commandPanel, BorderLayout.SOUTH); 
     add(mainPanel); 
    } 

    public void setTextArea(String text) { 
     displayTextArea.append(text); 
    } 

    private void enterButtonActionPerformed(java.awt.event.ActionEvent evt) { 
     setUserCommand(commandText.getText()); 
    } 

    public static void main(String args[]) { 
     java.awt.EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      WampusGUI w = new WampusGUI(); 
      w.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      w.pack(); 
      w.setLocationRelativeTo(null); 
      w.setVisible(true); 
      Game g = new Game(w); 
      g.play(); 
     } 
     }); 
    } 
} 

class Game { 
    private WampusGUI gui; 

    public Game(WampusGUI w) { 
     gui = w; 

     gui.addPropertyChangeListener(new PropertyChangeListener() { 

     @Override 
     public void propertyChange(PropertyChangeEvent pcEvt) { 

      // is the property being changed the one we're interested in? 
      if (WampusGUI.USER_COMMAND.equals(pcEvt.getPropertyName())) { 

       // get user command: 
       String userCommand = pcEvt.getNewValue().toString(); 

       // then we can do with it what we want 
       play(userCommand); 

      } 
     } 
     }); 
    } 

    public void play() { 
     gui.setTextArea("Welcome!\n"); 
     gui.setTextArea("Please enjoy the game!\n"); 
    } 

    public void play(String userCommand) { 
     // here we can do what we want with the String. For instance we can display it in the gui: 
     gui.setTextArea("User entered: " + userCommand + "\n"); 
    } 

} 
0

...

Ama durumunda u ur sorununa kirli çözüm sonra u bu deneyebilirsiniz istiyorum:

public class wampusGUI extends javax.swing.JFrame 
{ 
    private static wampusGUI myInstance; 
    public wampusGUI() 
    { 
     myInstance = this; 
     initComponents(); 
    } 

    public static void getUserCommand() 
    { 
     if(myInstance!=null) 
     { 
      return myInstance.commandText.getText(); 
     } 
     else 
     { 
      return null; 
     } 
    } 
    ...... 
    ...... 
} 

diğerinde sınıf kullanımı:

public void play() 
{ 
    ..... 
    //String s = userCommand; // here value should come should 
    String s = wampusGUI.getUserCommand(); 
    ..... 
} 

kod Bu tür bizim eski projelerin bazılarında var ... ve bundan nefret ediyorum.

+0

Buna gerek yok ve çok daha şık çözümler var. –

+0

Hiç bunun zarif bir çözüm olduğunu söylemedim;) –

+0

Doğru. Programcının veriyi bir dinleyici aracılığıyla ittiğini veya sorgulama yoluyla çekilmesini istediği sanırım. Mümkünse dinleyici yaklaşımını tercih ederim, ancak bu her zaman mümkün değildir. –

4

Kodunuzdaki bakıldığında belirli bir metnin

gui.setTextArea(welcome()); 
gui.setTextArea(describe()); 

ve bazen, bu diyalog sonradan işlenir kullanıcı girişi yakalamak gerektiğini ile kullanıcıya diyaloglar göstermek istiyorum görünüyor.

  1. Bu setTextArea çağrıları kullanmak istediğiniz değildir. Kullanıcı, karşılama mesajıyla hemen değiştirileceği için karşılama mesajını asla görmeyecektir.
  2. Olay Sevk İpliği'ni (EDT) engellemediğinizden emin olun, aksi takdirde hiçbir şey gösterilmeyecektir. Command sınıfının ne yapacağını bilmiyorum ama Event Dispatch Thread üzerinde sonsuz bir döngü görüyorum ki bu iyi bir şey değil.
  3. Daha fazla bilgi için Concurrency in Swing tutorial'a bir göz atın. for döngüsü sayesinde, kullanıcı EDT devrenizle meşgulken herhangi bir komut giremez. İhtiyacınız olan şey, kullanıcının giriş sağlamasına (EDT'yi engellememesine, ancak kodunuzun yürütülmesini engellemesine) olanak veren engelleme çağrısıdır. JOptionPane sınıfındaki statik yöntemler bunun için mükemmel şekilde uygundur (ör. JOptionPane#showInputDialog). Bu yöntemler ayrıca, kullanıcı girdisini çağrı koduna herhangi bir statik değişken olmadan ileterek, sorununuzu çözen bir mekanizmaya da sahiptir.
İlgili konular