Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: How to update Window from another thread  (Read 1430 times)

0 Members and 1 Guest are viewing this topic.

Wnt2bsleepin

  • Guest
How to update Window from another thread
« on: February 14, 2013, 06:28:21 am »
I made a basic animation that moves a ball around. Unfortunately, it freezes the main window. My solution was to run it in another thread. However, I am trying to pass a reference of the RenderWindow to my animation method. I am getting a NonCopyable error.

Here is the code:

#include <SFML/Graphics.hpp>
#include <iostream>
#include <ios>
#include <SFML/Window.hpp>
#include <SFML/OpenGL.hpp>
#include "main.h"

using namespace std;

//Hardcoded in.
bool running = true, runningSecondary = true;
const int XSize = 800, YSize = 600;
double countX = 0;
double countY = 0;



sf::CircleShape drawCircle(sf::RenderWindow& window2, sf::CircleShape circle = sf::CircleShape(100.f))
{
               
                circle.setFillColor(sf::Color::Green);
               
                window2.clear();
                window2.draw(circle);
                window2.display();

                return circle;
}

void changePos(bool reverse, char choice)
{
        if(reverse)
        {
                switch (choice)
                {

                case 'b':
                        countX -= .05;
                        countY -= .05;
                        break;
                case 'x':
                        countX -= .05;
                        break;
                case 'y':
                        countY -= .05;
                        break;
                }

        }

        else
        {
                switch (choice)
                {

                case 'b':
                        countX += .05;
                        countY += .05;
                        break;
                case 'x':
                        countX += .05;
                        break;
                case 'y':
                        countY += .05;
                        break;
                }
        }



}


void animate(sf::RenderWindow& window2, sf::CircleShape& circle)
{
        int circleDiameter = circle.getRadius() * 2;
       
        while(runningSecondary)
        {
                 
               
                if(countX >= 799 - circleDiameter)
                {
                        cout << circle.getPosition().x << " XXXXXX" << endl;
                        changePos(true, 'x');
                }

                else if(countY >= 599 - circleDiameter)
                {
                        cout << circle.getPosition().y << " YYYYYYYYY" << endl;
                        changePos(true, 'y');
                }

                else if((countX >= 799 - circleDiameter) && (countY >= 599 - circleDiameter))
                {
                        changePos(true, 'b');
                }

                else{changePos(false, 'b'); }

                circle.setPosition(countX,countY);
                drawCircle(window2, circle);
        }
}



int main()
{
    // create the window
        animateThread at;
       
    sf::Window window(sf::VideoMode(XSize, YSize), "OpenGL", sf::Style::Default, sf::ContextSettings(32));
        sf::RenderWindow window2(sf::VideoMode(XSize,YSize), "Graphics");
        sf::Clock clock;

    window.setVerticalSyncEnabled(true);
        glDisable(GL_DEPTH_TEST);
    // load resources, initialize the OpenGL states, ...

    // run the main loop
   
        sf::CircleShape circle = drawCircle(window2);
    while (running)
    {
        // handle events
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed)
            {
                // end the program
                running = false;
            }
            else if (event.type == sf::Event::Resized)
            {
                // adjust the viewport when the window is resized
                glViewport(0, 0, event.size.width, event.size.height);
            }
        }

                sf::Event Event_Window2;
                while(window2.pollEvent(Event_Window2))
                {
                        if(Event_Window2.type == sf::Event::Closed)
                        {
                                running = false;
                        }

                        else if(Event_Window2.type == sf::Event::KeyPressed)
                        {
                                if(Event_Window2.key.code == sf::Keyboard::P)
                                {
                                        runningSecondary = false;
                                }
                       
                        }

                         else if (Event_Window2.type == sf::Event::Resized)
            {
                // adjust the viewport when the window is resized
                glViewport(0, 0, Event_Window2.size.width, Event_Window2.size.height);
            }

                }

                //RenderWindow
               
                 
               
                //animate(window2,circle);
                animateThread at;
                at.circle = circle;
                at.window = window2; //I believe this is throwing the error.

                sf::Thread animationThread(&animate, at);
                //OpenGL Implementation Attempt.

        // clear the buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // draw...

                glBegin(GL_TRIANGLES);
                glVertex3f(100.0f, 100.0f, 0.0f);
                glVertex3f(150.0f, 100.0f, 0.0f);
                glVertex3f(125.0f, 50.0f, 0.0f);
                glEnd();
               
        // end the current frame (internally swaps the front and back buffers)
        window.display();
    }

    // release resources...

    return 0;
}


Header

#ifndef GUARD_main
#define GUARD_main

#include <SFML/Window.hpp>

struct animateThread{
    sf::Window window;
        sf::CircleShape circle;
};


#endif

The error is when I try to copy the RenderWindow  to my struct to pass it to my animate method.

Any help is much appreciated.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: How to update Window from another thread
« Reply #1 on: February 14, 2013, 08:11:12 am »
You can't copy windows (think about what would happen: a copy of the physical window would pop up ;)), so you have to store either references or pointers. In your case, you need a pointer because you can't bind a reference after its construction.
Laurent Gomila - SFML developer

Wnt2bsleepin

  • Guest
Re: How to update Window from another thread
« Reply #2 on: February 14, 2013, 10:22:54 pm »
So, I would need to assign the window object to a pointer variable and pass that on?

I am having a bit of a hard time passing a pointer to my struct.

animateThread at; //Struct object  
                at.circle = circle;
                at.RenderWindow = window2
 

I need to pass two parameters to my animate method, some googling showed that a struct was the way to do it.
« Last Edit: February 14, 2013, 10:31:03 pm by Wnt2bsleepin »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: How to update Window from another thread
« Reply #3 on: February 14, 2013, 10:42:55 pm »
sf::RenderWindow* w;
...
w = &window;
Laurent Gomila - SFML developer