2014-02-15 168 views
0

好的我現在編輯了這篇原文的所有內容。我回到了Visual Studio 2010,並創建了一個新項目並編碼了相同的東西,除了只編碼最低限度以獲得我之前的相同障礙。這意味着我在這裏發佈整個項目代碼,但它也很短並且可讀。我也收錄了一些評論,以便更容易遵循。 只是一個概括:這個問題是我不能夠成功地調用Form1.refreshScore()從其它類比Form1中本身你如何從另一個班級調用一個班級的方法?

public partial class Form1 : Form 
{ 
    private Enemy enemy_; 
    private Graphics paper_; 
    private bool started_; 


    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void timer_Tick(object sender, EventArgs e) 
    { 
     pictureBox.Refresh(); 
    } 
    private void pictureBox_Paint(object sender, PaintEventArgs e) 
    { 
     if (started_) 
     { 
      paper_ = e.Graphics; 
      enemy_.Draw(paper_); 
     } 
    } 

    public void refreshScore() 
    { 
     label.Text = "TEST"; //doesn't show 
     enemy_.color = Color.Red; //"Null Reference Exception unhandled" ? 
    } 

    private void Form1_KeyDown(object sender, KeyEventArgs e) 
    { 
     if(e.KeyCode == Keys.Space) 
     { 
      enemy_ = new Enemy(0, pictureBox.Height-20, 20, 100, 2, Color.Blue); 
      paper_ = pictureBox.CreateGraphics(); 
      started_ = true; //succeeds 
     } 
     if (e.KeyCode == Keys.K) 
     { 
      enemy_.Kill(); 
      enemy_.color = Color.Green; //succeeds. 
     } 
    } 



} 

    class Enemy 
{ 
    private float x_; 
    private float y_; 
    private float diameter_; 
    private float health_; 
    private float walkSpeed_; 
    private Color color_; 

    private Form1 form_ = new Form1(); 

    //Overloader 
    public Enemy() 
    { 
     x_ = 1; 
     y_ = 50; 
     diameter_ = 20; 
     walkSpeed_ = 1; 
     health_ = 100; 
     color_ = Color.Blue; 
    } 
    //Constructor, called in Form1, keydown event ("Space") 
    public Enemy(float x, float y, float diameter, float health, float walkSpeed, Color color) 
    { 
     x_ = x; 
     y_ = y; 
     diameter_ = diameter; 
     health_ = health; 
     walkSpeed_ = walkSpeed; 
     color_ = color; 
    } 

    //getter/setter for 'color' property 
    public Color color 
    { 
     get { return color_; } 
     set { color_ = value; } 
    } 

    public void Draw(Graphics paper) 
    { 
     SolidBrush brush = new SolidBrush(color_); 
     paper.FillRectangle(brush, x_,y_,x_ + diameter_, y_ + diameter_); 
    } 

    //called in Form1 under KeyDown event ("K") 
    public void Kill() 
    { 
     form_.refreshScore(); 
    } 
} 
+2

有大量關於如何從另一個班級調用班級的示例。除非有特定的問題,否則不需要像這樣的新問題,並且在你的情況下看起來並不像那樣,因爲看起來你只是想找到辦法。開始看這個問題的答案http://stackoverflow.com/questions/2950326/calling-a-function-in-the-form-class-from-another-class-c-sharp-net – FeliceM

+0

是的,你'這是對的(我真的很抱歉這樣做,我知道這很煩人)。但是我已經看過那個頁面(和其他許多頁面),它們似乎都提出了相同的解決方案,但它們都對我沒有意義。 解決方案與此類似:將所有的類/方法都變成「靜態」類型 - 我不太明白這意味着什麼,它立即導致我的所有代碼都顯示編譯錯誤。 我是C#的新手,無法理解我需要做什麼以便有一個可引用的對象來使用點符號調用方法(如上例所示),因爲這似乎是最簡單的... – ZOMGbies

+0

順便說一句,你可以只是將一段代碼粘貼到文本編輯器中,然後突出顯示它並單擊'{}'按鈕使其成爲代碼示例。 –

回答

1

我假設你有一個WinForms應用程序,而Form1是在你的項目中創建的默認窗體類。

在這種情況下,您的應用程序可能會發生什麼主要方法是創建一個Form1的實例並顯示它。然而,你的Enemy類是創造它自己Form1類的實例:

Form1 form1 = new Form1(); 

這從被顯示的一個是一個完全不同的實例。您需要爲您的Enemy顯示正在顯示的實例。也許最簡單的方法是讓Form1創建一個Enemy的實例並將this傳遞給它。例如:

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 

     _enemy = new Enemy(this); 
    } 

    private Enemy _enemy; 
} 

然後你Enemy類將是這個樣子:

public class Enemy 
{ 
    public Enemy(Form1 form) 
    { 
     _form1 = form; 
    } 

    // DON'T initialize this with new Form1(); 
    private Form1 _form1; 
} 

現在你Form1被創建的時候,它會創建的Enemy一個實例,然後將得到的一個參考形成。

+0

+1 LOL我沒有想到這一點!我多麼愚蠢。在「DeathCheck」方法而不是「Enemy」類中傳遞表單實例會更合適嗎? :) –

+0

那麼,這真的取決於所有這些將如何使用。如果這種方法是'敵人'需要與表單交互的唯一時間,那麼我會說是。如果'Enemy'需要更頻繁地與表單交互,我會拒絕。一般來說,我不認爲我會在表單上直接操作非形式類。相反,我可能會從表格中獲取來自'Enemy'的數據,然後處理如何以及在哪裏展示它自己。 – Kyle

+0

我同意我會將表單照顧到顯示器本身。在這種情況下,我可能會通過引用參數來傳遞參數,以返回'killedCount',或傳遞標籤控件而不是整個表單。還是有更好的方法來處理它,考慮到該方法本身返回布爾? –

1

您必須添加static到類方法

public class Class1 
{ 
    public static void MyMethod(float x) 
    { 
     return x*x ; 
    } 
} 

你打電話給你的方法是這樣的:

float y = Class1.MyMethod(5.24); 
+0

這就是我的谷歌搜索也告訴我的。 BUt每當我這樣做,我得到這個編譯錯誤的每個變量: 「一個對象引用是必需的非靜態字段,方法或屬性...」 – ZOMGbies

0

答案已經在你的代碼中ovided。

  1. Instantiate包含要調用的方法的類。 ClassName object = new ClassName();
  2. 使用您創建的類實例調用方法。 object.MethodName()

另一種方法是將您的方法聲明爲static。如果你聲明你的方法是靜態的,你不需要在調用方法之前實例化你的類(即不要執行第1步)。例如:

public class Class1 
{ 
    public static void Method1() 
    { 
     //some code 
    } 
} 

public class Class2 
{ 
    Class1.Method1(); //you do not need to instantiate the class if your method is static 
} 

PS:如果你申報你的方法作爲static但嘗試調用使用類(object.MethodName)的實例方法,你會得到一個編譯錯誤,說你不應該用一個實例來調用一個靜態方法。

我建議你仔細閱讀這些參考資料以便更好地理解:ref 1,ref 2,ref 3。更好的是,你應該選擇一本關於面向對象編程的書。

+0

是啊,我想實例類,因爲你看到我的上面的虛擬代碼,即時通過按照無數個教程一字一句的方式來做到這一點,而且它根本不會調用這些方法。它的編譯和運行,但我唯一的結論是,它試圖調用一個不是形式的對象;即一個「空白」的新的不是真正的一個?呃,對不起,我還沒有編碼詞彙尚未; P 每當我添加靜態任何東西,我得到編譯錯誤:「一個對象引用是非靜態字段,方法或屬性...所需的」 – ZOMGbies

+0

@ZOMGbies我不確定我是否理解「空白新表單」的含義。但是,請確保您將*方法*聲明爲靜態。並且請檢查你是不是試圖從靜態方法中調用非靜態方法。這是行不通的,因爲靜態方法沒有要調用的類的實例。 –

+0

'public static void refreshKillCount() { label.Text =「TEXTHERE」; }' 這是給我上面提到的編譯錯誤... – ZOMGbies

相關問題