Access violation when setting size and position of button

Started by Alpgh367, 13 April 2017, 06:23:39

Alpgh367

Hi,
While trying to set the size and position of a button with TGUI I am receiving an access violation error. I am using Visual Studio 2015 community, I downloaded the precompiled library, and I am linking dynamically. This is the code that is causing the error:
#include "Sidebar.h"
#include "App.h"

std::shared_ptr<tgui::Button> Sidebar::homeButton()
{
tgui::Button::Ptr button = tgui::Button::create("Home");
button->setPosition(500, 200);
button->setSize(200, 200);
App app;
app.gui.add(button, "homeButton");

return button;
}


The code runs with no errors without the setPosition and setSize, leading me to believe that they are the ones causing the issue. Any help is highly appreciated, thanks!

Alpgh367

I have managed to fix the Access Violation error but now when running the program the window rapidly flashes and the button is not rendered. Any fix to this would be great.

texus

You should create a minimal example code that shows this problem. I can't help much by only seeing a small part of the code or if you have too much code.

This might be what you already fixed, but the code in Sidebar::homeButton seems very wrong. You create the App instance inside it which creates the tgui::Gui instance to which you add the widget. But when you return from that homeButton function the App and Gui are destroyed as they go out of scope.

Alpgh367

I am not overly experienced in C++ but I have tried to fix the code you have mentioned, although I think I may have done so unsuccessfully. Here is more of my code:

Sidebar class (what I have attempted to fix)

#include "Sidebar.h"
#include "App.h"

Sidebar::Sidebar()
{
App app;
tgui::Button::Ptr button = tgui::Button::create("Home");
homeButton(button);
app.gui.add(button, "homeButton");
}

std::shared_ptr<tgui::Button> Sidebar::homeButton(std::shared_ptr<tgui::Button> button)
{
button->setPosition(600, 600);
button->setSize(200, 200);
button->setText("test");
button->setTextSize(20);
return button;
}


App class (I have publicly declared my gui object in the app header)
#include "App.h"
#include "Sidebar.h"

const sf::Time App::timePerFrame = sf::seconds(1.f / 60.f);

App::App()
{
mWindow.create(sf::VideoMode(1280, 720), "Study Buddy", sf::Style::Default);
gui.setWindow(mWindow);
}

void App::run()
{
sf::Clock clock;
sf::Time timeSinceLastUpdate = sf::Time::Zero;
while (mWindow.isOpen())
{
sf::Time elapsedTime = clock.restart();
timeSinceLastUpdate += elapsedTime;
while (timeSinceLastUpdate > timePerFrame)
{
timeSinceLastUpdate -= timePerFrame;

processEvents();
update(timePerFrame);
}

render();
}
}

void App::processEvents()
{
sf::Event event;

while (mWindow.pollEvent(event))
{
switch (event.type)
{
case sf::Event::KeyPressed:
handleUserInput(event.key.code, true);
break;

case sf::Event::KeyReleased:
handleUserInput(event.key.code, false);
break;

case sf::Event::Closed:
mWindow.close();
break;
}

gui.handleEvent(event);
}
}

void App::update(sf::Time elapsedTime)
{

}

void App::render()
{
mWindow.clear();
Sidebar s;
gui.draw();
mWindow.display();
}

void App::handleUserInput(sf::Keyboard::Key key, bool isPressed)
{
if (key == sf::Keyboard::Escape)
mWindow.close();
}


Unfortunately, I am still getting the rapidly flashing window with this code. Thanks for your help so far.

texus

You might want to have a look at what scopes are again, because it is important to understand how it works in c++.

The first line in Sidebar::Sidebar is still creating a new "app" which only exists until the end of the function and is then destroyed. Every frame you are creating a new Sidebar instance, the constructor will be executed and you create and destroy this App, this would cause a window to be created and immediately disappear.

The app should only be created in one place, the main function:
Code (cpp) Select
int main()
{
    App app;
    app.run();
}


The Sidebar should probably not be created every frame but e.g. be part of the App class:
Code (cpp) Select
class App
{
private:
    sf::RenderWindow mWindow;
    tgui::Gui mGui;
    Sidebar mSidebar;
public:
    App();
    void run();
    ...
}

Code (cpp) Select
App::App() :
    mWindow{{1280, 720}, "Study Buddy"},
    mGui{mWindow},
    mSidebar{mGui}
{
    // If you don't understand what the lines above are, look up "member initializer list"
}

Code (cpp) Select
void App::render()
{
mWindow.clear();
mGui.draw();
mWindow.display();
}


The Sidebar gets a reference to the gui as parameter and adds the button to it:
Code (cpp) Select
Sidebar::Sidebar(tgui::Gui& gui) // Passing by reference is important, we don't want to create a copy
{
tgui::Button::Ptr button = homeButton();
gui.add(button, "homeButton");
}

Code (cpp) Select
std::shared_ptr<tgui::Button> Sidebar::homeButton()
{
        auto button = tgui::Button::create("Home");
button->setPosition(600, 600);
button->setSize(200, 200);
button->setText("test");
button->setTextSize(20);
return button;
}


(Note that the code above is not complete and I didn't test any of the code so try to understand it instead of copying blindly)

Alpgh367

Thank you so much for all your help!!!! Everything is working now!!   ;D ;D ;D