2014-02-15 213 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

相关问题