Question Can't use System.Drawing after Application.Run() in Gtk#

BlueMagma3141

Member
Joined
Jun 29, 2019
Messages
6
Programming Experience
1-3
I am fairly new to using C# and I am creating applications using Gtk in MonoDevelop. I can make simple static drawings, but I am unable to create a loop of drawing multiple objects.
I currently have an interval set up using System.Timers to draw every sixtieth of a second. This is being used to simply move a rectangle and bounce it off the edges. However, it seems that nothing is drawn after Application.Run() is called.

Main Method:
    public static void Main()

    {

        Application.Init();

        Window w = new Window("Drawing");

        w.SetDefaultSize(width, height);


        canvas = new DrawingArea();

        canvas.ExposeEvent += ExposeHandler;

        canvas.SizeAllocated += SizeAllocatedHandler;


        SetupPensBrushes();


        Box box = new HBox(true, 0)

        {

            canvas
        };

        w.Add(box);

        w.ShowAll();

        w.DeleteEvent += Quit;


        Application.Run();

    }
Other useful code:
  public static void ExposeHandler(object obj, ExposeEventArgs args)
    {
        ev = args.Event;
        window = ev.Window;
        ctx = Gtk.DotNet.Graphics.FromDrawable(window);
        FillRect(new SolidBrush(Color.Black), 0, 0, width, height); // (Custom function for a rectangle) This works and creates a black background 
        interval.Interval = 1000 / 60;
        interval.Elapsed += ElapsedEvt;
        interval.Start(); // 'ElapsedEvt' includes moving and drawing an object, but it cannot be seen on the screen. 
    }

    public class Obj
    {
        public int x;
        public int y;
        public int w;
        public int h;
        public int xv = rnd.Next(-width / 50, width / 50);
        public int yv = rnd.Next(-height / 50, height / 50);

        public Obj(int x, int y, int w, int h)
        {
            this.x = x;
            this.y = y;
            this.w = w;
            this.h = h;
        }

        public void Move()
        {
            x += xv;
            y += yv;
        }

        public void Show()
        {
            FillRect(Brushes["LightBlue"], x, y, w, h);
        }
    }

    public static void ElapsedEvt(object sender, ElapsedEventArgs e)
    {
        boxObj.Move();
        boxObj.Show();
        // boxObj has been defined already as a new Obj()
    }
 
Have you tried setting a breakpoint on ElapsedEvt to verify that the timer's event handler is being called?

I don't know enough about how GTK# works. I don't know how sensitive it is to cross thread calls. As I recall, the System.Timers.Timer.Elapsed event handler is called back from another thread (which may come from a thread pool).
 
Have you tried setting a breakpoint on ElapsedEvt to verify that the timer's event handler is being called?

I don't know enough about how GTK# works. I don't know how sensitive it is to cross thread calls. As I recall, the System.Timers.Timer.Elapsed event handler is called back from another thread (which may come from a thread pool).
Yes, it would still output to console but not draw anything.

It turns out I needed to use canvas.QueueDraw() to run the expose event, but there is still lag within the program (maybe some things not properly disposed?)
 
Based on your line interval.Interval = 1000 / 60;, you are assuming that GTK# can render at 60 frames per second. Do know if GTK# can even do that frame rate?
 
Based on your line interval.Interval = 1000 / 60;, you are assuming that GTK# can render at 60 frames per second. Do know if GTK# can even do that frame rate?
That's true, I have since set it to 30 frames per second and it runs for about 10 seconds before lagging.
 
A screenshot wouldn't provide much; it's just a simple rectangle with a random speed that bounces off of the edges. It runs smoothly for a few seconds, but then lags terribly.
 
Hmm, you could gif it, or even better record a short mp4 clip... I just wanted to see how it looks. If you got a lot of stuff going on in your UI/main thread, you will experience scaling and even lag. Does the rectangle take up most of the screen or only a small portion?

I am no expert on GTK either, but I read that the frame rates are not an issue at 60 frames.

Have you checked for possible memory leaks?

You should also add the ability to stress/load/performance test your application, as this will help to identify where your lag may be coming from. I am sure, Skydiver might have some advice for you on that route if you wish to consider it.
 
How many times is ExposeHandler() called? If it is called multiple times, notice how you are registering an event handler each time it is called. So each time the timer Elapsed event is fired, not it has to call each of those registered event handlers.
 
Back
Top Bottom