簡體   English   中英

白色方形 SFML

[英]White square SFML

我在嘗試顯示帶紋理的按鈕時遇到了 SFML C++ 的白色方塊問題 我有一個繼承自Button.hImageButton.h 紋理已成功加載(在調試器中檢查)。 但最后,我看到了一個白色的方塊 如何解決?

按鈕.h

#ifndef BUTTON_H
#define BUTTON_H

#include<SFML/Graphics.hpp>

class Button
{
public:
    Button();
    Button(sf::Vector2f size, sf::Vector2f pos,sf::Color outlineColor, float sizeOutline);
    void virtual draw(sf::RenderWindow* w) = 0;
protected:
    sf::RectangleShape frame;
};



#endif // !BUTTON_H

按鈕.cpp

#include "Button.h"

Button::Button()
{
}

Button::Button(sf::Vector2f size, sf::Vector2f pos,sf::Color outlineColor, float sizeOutline)
{
    frame.setPosition(pos);
    frame.setSize(size);
    frame.setOutlineColor(outlineColor);
    frame.setOutlineThickness(sizeOutline);
}


圖像按鈕.h

#ifndef IMAGE_BUTTON_H
#define IMAGE_BUTTON_H

#include"Button.h"

class ImageButton : public Button
{
public:
    ImageButton();
    ImageButton(sf::Vector2f size, sf::Vector2f pos, sf::Color outlineColor, float sizeOutline, std::string path);
    void draw(sf::RenderWindow* w);
private:
    sf::Texture backTexture;
    sf::Sprite background;
};


#endif // !IMAGE_BUTTON_H

圖像按鈕.cpp

#include "ImageButton.h"

ImageButton::ImageButton()
{
}

ImageButton::ImageButton(sf::Vector2f size, sf::Vector2f pos, sf::Color outlineColor, float sizeOutline, std::string path)
    : Button(size,pos,outlineColor,sizeOutline)
{
    
    backTexture.loadFromFile(path, sf::IntRect(sf::Vector2i(pos.x,pos.y),sf::Vector2i(size.x,size.y)));
    backTexture.setSmooth(true);
    background.setTexture(backTexture);
    background.setPosition(pos);
}

void ImageButton::draw(sf::RenderWindow* w)
{
    w->draw(this->background);
    w->draw(this->frame);
}

程序.h

#ifndef PROGRAMM_H
#define PROGRAMM_H

#include<SFML/Graphics.hpp>
#include"ImageButton.h"


class programm
{
public:
    programm();
    void run();
private:
    ImageButton b;
    sf::RenderWindow* window;
    sf::Event e;
    void render();
    void update();

};
#endif // !PROGRAMM_H

程序.cpp

#include "programm.h"

programm::programm()
{
    this->window = new sf::RenderWindow(sf::VideoMode(600, 600), "Novel Editor", sf::Style::Close);
    this->window->setPosition(sf::Vector2i(0, 0));
    this->window->setFramerateLimit(60);
    this->b = ImageButton(sf::Vector2f(50.f, 50.f), sf::Vector2f(50.f, 50.f), sf::Color::Yellow, 5.f, "images\\putin.png");
}

void programm::run()
{
    while (this->window->isOpen())
    {
        while (this->window->pollEvent(e))
        {
            update();
        }
    }
}

void programm::render()
{
    this->window->clear();
    b.draw(this->window);
    this->window->display();
}

void programm::update()
{
    switch (e.type)
    {
    case sf::Event::Closed:
    {
        this->window->close();
        break;
    }
    default:
        break;
    }

    render();
}

截屏

在此處輸入圖像描述

您和其他人( 在 redditSO其他地方)面臨的問題是由sf::Sprite的構造函數和賦值運算符的(未)實現方式引起的:由於開發人員決定不實現專門的功能並且沒有t 使它們私有,編譯器提供不知道m_texture指針語義的默認值,因此執行二進制復制。 這可能不是最好的方法,但它已記錄在案

因此,如果您在 class 中使用sf::Sprite成員而不采取特殊措施進行復制,編譯器將假定默認賦值語義並因此調用sf::Sprite class 的(無效)賦值語義。 您在program中創建的本地ImageButton object 調用ImageButton的此默認分配

programm::programm()
{
    this->window = new sf::RenderWindow(sf::VideoMode(600, 600), "Novel Editor", sf::Style::Close);
    this->window->setPosition(sf::Vector2i(0, 0));
    this->window->setFramerateLimit(60);
    this->b = ImageButton(sf::Vector2f(50.f, 50.f), sf::Vector2f(50.f, 50.f), sf::Color::Yellow, 5.f, "images\\putin.png");
}

成員b中的Sprite從本地ImageButton中的Sprite接管指針texture ,其生命周期限於programm構造函數的 scope。 除此之外,您的成員b中的sprite包含對已破壞紋理 object 的引用,這導致未定義的行為(另請參見sf::Sprite Class 參考(SFML / Learn / 2.4.1 Documentation) ):

如果源紋理被破壞並且精靈嘗試使用它,則行為未定義。

順便說一句,我建議在program class 中直接使用sf::RenderWindow window而不是通過指針,因此您可以將代碼更改為類似的內容(請注意,我使用button而不是b並縮短了內聯實現簡潔)。

class programm
{
public:
    programm():
        window(sf::VideoMode(600, 600), "Novel Editor", sf::Style::Close);
        button(sf::Vector2f(50.f, 50.f), sf::Vector2f(50.f, 50.f), 
        sf::Color::Yellow, 5.f, "images\\putin.png")
    {
        window->setPosition(sf::Vector2i(0, 0));
        window->setFramerateLimit(60);
    }
    // ...
private:
    // ...
    sf::RenderWindow window;
    ImageButton button;
};

另一種選擇是為您的ImageButton class 提供一個專門的賦值運算符( thakee nathees 顯示如何)或復制構造函數,它負責處理紋理 object 的深層副本。

或者,您可以考慮為sf::Sprite實現一個包裝器 class 來解決此問題,並將其用於您的應用程序。

programm::programm()
{
    ...
    this->b = ImageButton(...); //< this line cause the bug
}

您正在通過從本地ImageButton分配來初始化圖像按鈕this->b 現在精靈將擁有本地實例紋理的紋理引用,當本地實例“死亡”時,紋理將被釋放。 您需要保持紋理的生命周期

解決方案1 :覆蓋賦值運算符並像這樣設置紋理

ImageButton& operator=(const ImageButton& ref) {
        backTexture = ref.backTexture;
        background = ref.background;
        background.setTexture(backTexture);
        return *this;
}

解決方案2 :創建一個TextureManager並將其作為您所有程序的紋理API,通過它保持您的紋理生命周期。

解決方案3 :在programm構造函數中初始化圖像按鈕

programm::programm()
    :b (sf::Vector2f(50.f, 50.f), sf::Vector2f(50.f, 50.f), sf::Color::Yellow, 5.f, "img.jpg")
{
   ...
}

另一個錯誤

void ImageButton::draw(sf::RenderWindow* w)
{
    w->draw(this->background);
    w->draw(this->frame);
}

您在背景之后繪制框架,默認情況下框架的填充顏色為白色

解決方案1 :先畫框,再畫背景

解決方案 2 :將框架填充顏色 alpha 設置為 0

Button::Button(sf::Vector2f size, sf::Vector2f pos, sf::Color outlineColor, float sizeOutline)
{
    frame.setPosition(pos);
    frame.setSize(size);
    frame.setOutlineColor(outlineColor);
    frame.setFillColor(sf::Color(0, 0, 0, 0)); // <----
    frame.setOutlineThickness(sizeOutline);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM