• Advertisement

C# - "Object reference not set to an instance of an object"

Recommended Posts

I am trying to create a simple GUI system, with buttons and text for now, but this little problem has me absolutely stumped. Basically, I'm creating a new instance of the class GUI and giving it a reference of the newly created window (wnd) which then stores it in the variable "w". With that, I loop through all the current buttons and draw it using the window's draw function (w.Draw()) but the variable "w" always ends up being null and giving me that error. Here's part of my code:

// Program.cs
static void Main(string[] args)
	{
		RenderWindow wnd = new RenderWindow(new VideoMode(800, 600), "Test");
		Font font = new Font("ITCBLKAD.TTF");
 		GUI gui = new GUI(ref wnd);
            
		wnd.Closed += new EventHandler(CloseEvn);

		while (wnd.IsOpen)
		{
			wnd.DispatchEvents();
 			wnd.Clear();
			gui.RenderAll();
			wnd.Display();
		}
  	// ...
// GUIHandler.cs
class GUI
{
	protected RenderWindow w;
	static protected List<Button> buttonContainer = new List<Button>();

	public GUI() { }

	public GUI(ref RenderWindow window)
	{
		w = window;
	}

	public void RenderAll()
	{
		foreach (Button obj in buttonContainer)
		{
			obj.Draw();
		}
   	}
}
  
class Button : GUI
{
	Text textObj;
  	FloatRect rect;
 	RectangleShape shape;
        
   	Vector2f vec;
   	State state;
	readonly string type = "button";

	private Button(string text, Font _font, float xpos, float ypos, State _state)
	{
		vec.X = xpos;
		vec.Y = ypos;
		textObj = new Text(text, _font);
		textObj.Position = vec;
		state = _state;
		rect.Left = xpos;
		rect.Top = ypos;
		rect.Width = 10;
		rect.Height = 10;
	}

	public static Button NewText(string text, Font _font, float xpos, float ypos, State _state)
	{
		Button temp = new Button(text, _font, xpos, ypos, _state);
      
		buttonContainer.Add(temp);

		return temp;
	}
  
	public void Draw()
	{
		w.Draw(textObj);
	}
}

Is there anything I'm missing? I'll post the whole code if needed.

Share this post


Link to post
Share on other sites
Advertisement

The whole code is usually better :)

My educated guess: You use the parameterless of GUI inside your Button class, thus w stays uninitialised ( = null )

You either need to pass RenderWindow into all your GUI components or, probably cleaner, use RendererWindow as parameter to Draw and not as member at all.
 

 

Share this post


Link to post
Share on other sites

This has nothing to do with the problem your having, I think Endurion is right about it, but I noticed this code:

4 hours ago, louie999 said:

public static Button NewText(string text, Font _font, float xpos, float ypos, State _state) { Button temp = new Button(text, _font, xpos, ypos, _state); buttonContainer.Add(temp); return temp; }

Wouldn't it be easier to just set textObj to use the data from the parameters of this function? Also, I don't see the point of adding a temporary Button to buttonContainer and returning the temporary Button, especially not to just set new text.

Share this post


Link to post
Share on other sites

Why is GUI.buttonContainer static?  You're going to always be drawing all of your buttons on all of your GUIs, so at best if you've got two of these top-level GUI objects, you're going to draw every button to whatever window it's supposed to be in twice.

Unless there is more we're not seeing, I don't really see the point of Button subclassing GUI, either...

Share this post


Link to post
Share on other sites

Thanks for the response, guys. :) I've re-written the code for that so it should hopefully be better now.

@Endurion You're right, that was the problem. I believe I've managed to fix it now when I re-written it. :)

@Yxjmir Well, the reason I'm returning the newly created button is that I do have some other functions that set other things (Like color, and perhaps textures in the future).

@ericrrichards22 Yeah, sub-classing it to GUI was quite useless, I've changed that now though :). The reason I made buttonContainer static is because it's where all the buttons would be stored. It's also being used in a foreach loop to update/draw the buttons.

Here's the updated code. Though it is still quite unfinished, it did manage to do some basic stuff like respond to button clicks through the event handler. But is there any thing else that needs to be improved? Or perhaps changed?

namespace TestApp
{
    namespace GUI
    {
        public delegate void MouseOverObjectEventHandler(object sender, OnMouseOverObjectEventArgs e);

        #region Event Args

        public class OnMouseOverObjectEventArgs : EventArgs
        {
            public float mx, my;
            public Mouse.Button ButtonPressed;
            public object Source;

            public OnMouseOverObjectEventArgs(float x, float y, Mouse.Button buttonPressed, object source)
            {
                mx = x;
                my = y;
                ButtonPressed = buttonPressed;
                Source = source;
            }
        }

        #endregion

        static class Renderer
        {
            public static RenderWindow Window;
            public static List<Button> ButtonContainer = new List<Button>();

            static public event MouseOverObjectEventHandler OnMouseOver;

            public static void Init(ref RenderWindow window)
            {
                Window = window;
            }

            public static void DrawGUI()
            {
                foreach (Button obj in ButtonContainer)
                {
                    obj.Draw();
                }
            }

            public static void Update(float mx, float my, Mouse.Button buttonPressed)
            {
                foreach (Button obj in ButtonContainer)
                {
                    if (obj.Area.Contains(mx, my))
                    {
                        OnMouseOver?.Invoke(obj, new OnMouseOverObjectEventArgs(mx, my, buttonPressed, obj));
                    }
                }
            }
        }

        public class State
        {
            int id;
            static public State currentState;

            public State(int n)
            {
                id = n;
            }

            public static void SetState(State state)
            {
                currentState = state;
            }

            public override bool Equals(object obj)
            {
                State other = (State)obj;
                return this.id == other.id;
            }
        }

        class Button
        {
            Text DisplayText = new Text();
            Font font;
            RectangleShape Rect = new RectangleShape();
            public FloatRect Area = new FloatRect();
            float Xpos, Ypos, Width, Height;
            State state;
            bool IsHidden = false;

            #region Constructor & Adder

            private Button(string text, Font font, Vector2f position, Vector2f size, State _state)
            {
                DisplayText.DisplayedString = text;
                DisplayText.Font = font;
                DisplayText.Position = position;

                Rect.Position = position;
                Rect.Size = size;

                Area.Left = position.X;
                Area.Top = position.Y;
                Area.Width = size.X;
                Area.Height = size.Y;

                state = _state;
            }

            static public Button New(string text, Font font, Vector2f position, Vector2f size, State _state)
            {
                var newButton = new Button(text, font, position, size, _state);
                Renderer.ButtonContainer.Add(newButton);

                return newButton;
            }

            #endregion

            #region Set Methods

            public Button SetText(string text)
            {
                DisplayText.DisplayedString = text;

                return this;
            }

            public Button SetTextColor(Color color)
            {
                DisplayText.Color = color;

                return this;
            }

            public Button SetBackgroundColor(Color color)
            {
                Rect.FillColor = color;

                return this;
            }

            public Button SetPosition(Vector2f pos)
            {
                DisplayText.Position = pos;

                return this;
            }

            public Button SetFont(ref Font font)
            {
                DisplayText.Font = font;

                return this;
            }

            public Button SetVisibility(bool visibility)
            {
                IsHidden = visibility;

                return this;
            }

            #endregion

            #region Get Methods

            public string GetText()
            {
                return DisplayText.DisplayedString;
            }

            public bool GetVisibility()
            {
                return IsHidden;
            }

            #endregion

            public void Draw()
            {
                if (!IsHidden && state == State.currentState)
                {
                    Renderer.Window.Draw(Rect);
                    Renderer.Window.Draw(DisplayText);
                }
            }
        }
    }
}

 

Edited by louie999

Share this post


Link to post
Share on other sites

You don't need to pass parameters with 'ref' if (you don't need to reassign that variable at the call site) && (are not doing it to match a virtual function signature) && (the type is not a large value type that you're trying to prevent pass-by-value from copying the whole thing).

Edited by Nypyren

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By Dave Haylett
      Hi all. My project is coming along wonderfully, and am starting to consider alpha deployment, and would like your advice.
      My project need access to 10,000 small PNG image files at runtime, each is only a few kilobytes each, which during development I used to load in directly from a fixed path on my HDD whenever one was needed (obviously not a solution for go-live), using something like this:
      img = new WriteableBitmap(new BitmapImage(new Uri(@screenshotsPath + filename)));
      The image would then be blitted onto a buffer screen, etc. etc. At a time, a few dozen would be being used.
      Now I'm thinking about deployment, and also when I produce an update to my app, there could be more images to add to the folders. So I'm considering the best way of a) deploying the images to the user as part of the project, and b) how to most easily handle updates to the app, whereby more images will be added.
      I have just experimented with adding them all as a Resource (!). This inflated the exe from 10mb to 100mb (not a major problem), increased the compile time from 3 secs to 30 secs (annoying), increased RAM usage from 500mb to 1.5gb (not a major problem either), but means that it solves my fixed directory issue, distribution issue, and update issue, simply by having the files all stuck into the executable. Here's the new code I'm using:
      img = BitmapFactory.FromResource("Shots/" + filename);
      The next thing I was going to try was to mark them as Content > Copy if Newer. This would resolve the executable size and RAM usage (and also the directory issue as well), however it seems that I'd need to highlight them all, and move them from Resource to Content. As an up-front job this isn't too bad, but as I add new images to the project, I'll need to go in and do this every time, which gets annoying, as the VS2015 default is Resource. Also, I'm not sure how this would work in terms of updates. Would something like ClickOnce deployment recognise new PNGs and install them to the users?
       
      I also have 3,000 ZIP files (~500kb each) which also need deploying and updating in the same way. These are currently read directly from my HDD until I can find a permanent solution for adding these to the project as well.
      Can anyone thing of a better way of doing what I'm trying to achieve?
      Thanks for any help folks.
       
    • By Felis Nigripes
      I'm doing a test quest.
      The player gets a quest from an NPC to bring him fish.

      Once the player picks up the fish, the original NPC gets replaced by a new one with a new conversation trigger. The NPC tells the Player "Well done" and should give 200xp.

      The script tells the xp counter to go up by making a reference to the gameobject that holds the text component
       
      But it throws this error:
       

       
      I'm aware that the error may hide in plain sight. I just have to sort this out, since I'm writing the AI at the same time, and the time it takes to resolve everyone of these errors is tremendous.
      Plus, I think I'll learn something. I've been having trouble with some basic functionalities recently. There might be something wrong with my understanding on how programming works.
       
      Glad if someone could help (:
       
       
       
      Edit: I'm fully aware that the update function requires an input. I call the function in the editor when the dialogue ends, it still doesn't work.
       
    • By Vu Chi Thien
      Hi fellow game devs,
      With the help of  @CombatWombat in my previous post about clutch modeling, I now have a solid direction for the modeling the clutch. The way I'm doing it is having 2 clutch states: locked and unlocked. EngineRPM and torque will be calculated separately in each state. My problem right now is the logic and code for specifying locking and unlocking.
      The condition for locking is when (engineSpeed - drivetrainSpeed) in previous update cross zero (different sign) with the current update (to determine if engineSpeed = drivetrainSpeed or not in-between updates) and engineTorque <= clutchTorque.
      The condition for unlocking is when engineTorque > clutchTorque.
      The diagram looks roughly like this (taken from matlab website with the similar implementation):

       
      However, the 2 conditions are triggers for switching states, not for determine the current state to be in, so in the end my clutch state just jumped around. I don't have a lot of experience in doing state machine, so can some one give me rough code of how to implement this? Below is my rough code:
      speedError = engineSpeed - drivetrainSpeed; if ((Math.Sign(speedError) != Math.Sign(deltaW) && currentTotalEngineTorque <= clutchReactTorque)) { clutchLocked = true; } else clutchLocked = false; deltaW = speedError; //end of update I think the main struggle is the cross zero. Because cross zero is the "trigger condition" to check if the clutch should lock when it is slipping, not the condition for continuous locking, while the code I have above is the "continuous condition" saying "this condition is true then it is locked/unlocked". Another word, if the clutch is slipping, the condition above would decide if it's locked or not, but once it is locked, the cross zero condition is not true anymore (since speedError and deltaW have same sign as engineSpeed == drivetrainSpeed when clutch is locked). I'm sorry that I cannot explain this better as English is not my first language.
    • By nxrighthere

      BenchmarkNet is a console application for testing the reliable UDP networking solutions.
      Features:
      Asynchronous simulation of a large number of clients Stable under high loads Simple and flexible simulation setup Detailed session information Supported networking libraries:
      ENet (C# Wrapper) UNet LiteNetLib Lidgren MiniUDP Hazel Photon Neutrino DarkRift More information and source code on GitHub.
      You can find the latest benchmark results on the wiki page.
    • By Timothy Sharp
      I need help on a script. I am recreating a scene from A Hat In Time where Hat Girl goes into Queen Vanessa's manor. She has to collect keys and avoid Queen Vanessa. How would I script the door where you can open it and peek through it without actually going out the door? Any help is appreciated. Thanks!

      EDIT: Not peeking throught the keyhole, just poke your head out the door
  • Advertisement