白色方形SFML 当我试图显示纹理按钮时,我面对了SFML C++。我有一个ImageButton.h,它继承了Button.h。已在调试器中成功加载纹理。但最后,我看到了一个白色的正方形。如何解决

白色方形SFML 当我试图显示纹理按钮时,我面对了SFML C++。我有一个ImageButton.h,它继承了Button.h。已在调试器中成功加载纹理。但最后,我看到了一个白色的正方形。如何解决,c++,sfml,C++,Sfml,按钮 ImageButton.h ImageButton.cpp 编程语言 截图 你和其他人的问题, , 和 是由构造函数和赋值运算符的方式引起的 sf::Sprite没有实现:因为开发人员决定不实现 编译器说,实现专门的函数,而不是使它们私有 提供不知道m_纹理语义的默认值 指针,从而进行二进制复制。这可能不是最好的方法,但是 因此,如果您在类中使用sf::Sprite成员而不使用 对于复制的特殊措施,编译器将采用默认赋值 因此调用的无效赋值语义 精灵类。在中创建的本地ImageButton

按钮

ImageButton.h

ImageButton.cpp

编程语言

截图


你和其他人的问题, , 和 是由构造函数和赋值运算符的方式引起的 sf::Sprite没有实现:因为开发人员决定不实现 编译器说,实现专门的函数,而不是使它们私有 提供不知道m_纹理语义的默认值 指针,从而进行二进制复制。这可能不是最好的方法,但是

因此,如果您在类中使用sf::Sprite成员而不使用 对于复制的特殊措施,编译器将采用默认赋值 因此调用的无效赋值语义 精灵类。在中创建的本地ImageButton对象 程序调用ImageButton的默认分配

program::program { 此->窗口=新建sf::RenderWindowWSF::VideoMode600600,小说编辑器,sf::Style::Close; 此->窗口->设置位置SF::Vector2i0,0; 此->窗口->设置帧速率限制60; 这->b=ImageButtonsf::Vector2f50.f,50.f,sf::Vector2f50.f,50.f,sf::Color::Yellow,5.f,images\\putin.png; } 成员b中的精灵从 本地ImageButton中的精灵,其生存期限制为 程序构造函数的作用域。除此之外,你心中的精灵 成员b持有对已破坏纹理对象的引用,该对象会导致 是未定义的行为,另请参见:

如果源纹理被破坏,精灵尝试使用它, 该行为未定义

顺便说一下,我建议直接在 程序类不是通过指针,所以您可以将代码更改为 就像这张便条,我用按钮代替了b,并缩短了内联 为了简洁起见,我们需要实现

班级计划 { 公众: 节目: windowsf::VideoMode600600,小说编辑器,sf::Style::Close; 按钮sf::Vector2f50.f,50.f,sf::Vector2f50.f,50.f, sf::颜色::黄色,5.f,图像\\putin.png { 窗口->设置位置SF::向量2i0,0; 窗口->设置帧速率限制60; } // ... 私人: // ... sf::RenderWindow窗口; 图像按钮; }; 另一种选择是提供专门的分配操作员 或者复制ImageButton类的构造函数,该类负责 纹理对象的深度复制

或者,您可以考虑为实现一个包装器类
sf::Sprite修复此问题,并将其用于您的应用程序。

您和其他人的问题, , 和 是由构造函数和赋值运算符的方式引起的 sf::Sprite没有实现:因为开发人员决定不实现 编译器说,实现专门的函数,而不是使它们私有 提供不知道m_纹理语义的默认值 指针,从而进行二进制复制。这可能不是最好的方法,但是

因此,如果您在类中使用sf::Sprite成员而不使用 对于复制的特殊措施,编译器将采用默认赋值 因此调用的无效赋值语义 精灵类。在中创建的本地ImageButton对象 程序调用ImageButton的默认分配

program::program { 此->窗口=新建sf::RenderWindowWSF::VideoMode600600,小说编辑器,sf::Style::Close; 此->窗口->设置位置SF::Vector2i0,0; 此->窗口->设置帧速率限制60; 这->b=ImageButtonsf::Vector2f50.f,50.f,sf::Vector2f50.f,50.f,sf::Color::Yellow,5.f,images\\putin.png; } 成员b中的精灵从 本地ImageButton中的精灵,其生存期限制为 程序构造函数的作用域。除此之外,你心中的精灵 成员b持有对已破坏纹理对象的引用,该对象会导致 是未定义的行为,另请参见:

如果源纹理被破坏,精灵尝试使用它, 该行为未定义

顺便说一下,我建议直接在 程序类不是通过指针,所以您可以将代码更改为 就像这张便条,我用按钮代替了b,并缩短了内联 为了简洁起见,我们需要实现

班级计划 { 公众: 节目: windowsf::VideoMode600600,小说编辑器,sf::Style::Close; 按钮sf::Vector2f50.f,50.f,sf::Vector2f50.f,50.f, sf::颜色::黄色,5.f,图像\\putin.png { 窗口->设置位置SF::向量2i0,0; 窗口->设置帧速率限制60; } // ... 私人: // ... sf::RenderWindow窗口; 图像按钮; }; A 另一种选择是提供一个专门的分配操作员 或者复制ImageButton类的构造函数,该类负责 纹理对象的深度复制

或者,您可以考虑为实现一个包装器类 sf::Sprite修复此问题,并将其用于应用程序。

programm::programm { ... 这->b=ImageButton…;//<这一行导致错误 } 您正在通过从本地ImageButton分配来初始化图像按钮this->b。现在,精灵将具有本地实例纹理的纹理引用,当本地实例消亡时,纹理将被释放。您需要保持纹理的生命周期

解决方案1:覆盖赋值操作符并像这样在那里设置纹理

ImageButton和运算符=常量ImageButton和ref{ 背纹理=参考背纹理; 背景=参考背景; background.setTexturebackTexture; 归还*这个; } 解决方案2:创建一个TextureManager,并将其作为所有程序的纹理API,通过它保持纹理的生命周期

解决方案3:在程序构造函数中初始化图像按钮

program::program :b sf::Vector2f50.f,50.f,sf::Vector2f50.f,50.f,sf::Color::Yellow,5.f,img.jpg { ... } 另一个错误 void ImageButton::drawsf::RenderWindow*w { w->drawthis->背景; w->drawthis->frame; } 您正在背景后绘制帧,默认情况下,帧的填充颜色为白色

解决方案1:先绘制帧,然后绘制背景

解决方案2:将帧填充颜色alpha设置为0

按钮::按钮sf::矢量2F大小,sf::矢量2F位置,sf::颜色大纲颜色,浮动大小线 { frame.setPositionpos; frame.setSizesize; frame.setOutlineColoroutlineColor; frame.setFillColorsf::Color0,0,0,0;//programm::programm { ... 这->b=ImageButton…;//<这一行导致错误 } 您正在通过从本地ImageButton分配来初始化图像按钮this->b。现在,精灵将具有本地实例纹理的纹理引用,并且当本地实例死亡时,纹理将被释放。您需要保持纹理的生存期

解决方案1:覆盖赋值操作符并像这样在那里设置纹理

ImageButton和运算符=常量ImageButton和ref{ 背纹理=参考背纹理; 背景=参考背景; background.setTexturebackTexture; 归还*这个; } 解决方案2:创建一个TextureManager,并将其作为所有程序的纹理API,通过它保持纹理的生命周期

解决方案3:在程序构造函数中初始化图像按钮

program::program :b sf::Vector2f50.f,50.f,sf::Vector2f50.f,50.f,sf::Color::Yellow,5.f,img.jpg { ... } 另一个错误 void ImageButton::drawsf::RenderWindow*w { w->drawthis->背景; w->drawthis->frame; } 您正在背景后绘制帧,默认情况下,帧的填充颜色为白色

解决方案1:先绘制帧,然后绘制背景

解决方案2:将帧填充颜色alpha设置为0

按钮::按钮sf::矢量2F大小,sf::矢量2F位置,sf::颜色大纲颜色,浮动大小线 { frame.setPositionpos; frame.setSizesize; frame.setOutlineColoroutlineColor;
frame.setFillColorsf::Color0,0,0;//据我所知,SFML是基于智能指针构建的,因此ImageButton对此->p的赋值可以工作,但取决于sf::Texture或sf::Sprite的赋值运算符是否正确实现。因此,我尝试将ImageButton构造函数参数列表移动到初始值设定项列表:b。顺便说一句:在这个->窗口中的new=new sf::RenderWindow…和sf::RenderWindow*窗口;在program.h中,我觉得很不一致,以这种方式混合自动变量和动态变量是很危险的。如果你看这个,你会看到相同的模式,一个自动播放器对象被分配给一个现有的播放器。看起来真的好像有什么东西在我所学的sf::Texture和sf::Sprite中,至少有一个赋值运算符出错,SFML是基于智能指针构建的,因此ImageButton对此->p的赋值可以工作,但取决于sf::Texture或sf::Sprite的赋值运算符是否正确实现。因此,我尝试移动ImageButton构造函数的列表初始值设定项列表的参数:b.BTW:the new in the->window=new sf::RenderWindow…和sf::RenderWindow*window;在program.h中,我觉得非常不一致,以这种方式混合自动变量和动态变量是危险的。如果你看这个,你会看到相同的模式,一个自动播放器对象被分配给一个现有的播放器。看起来sf::Texture和sf::Sprite中至少有一个赋值运算符出现了问题。这是一个多么详细的解释啊!看来你对库很熟悉,我现在才知道。你会说它很成熟吗
著名的白方问题?@Wolf谢谢,我也刚刚开始学习SFML。Sprite的内部纹理引用只是一个原始指针常量纹理*m_纹理,造成了所有的麻烦,我们需要保持纹理的生命周期。请阅读您的答案,它也有很好的解释+1您是否知道在一些SFML错误报告中是否已经解决了这一问题?我的意思是,我们看到文档没有告诉人们什么不该做。至少应该为sf:Sprite做私有拷贝,当然最好实现拷贝…我试图找到一个but报告,但是什么都没有。也许不复制是出于性能原因?使用TextureManager似乎很有趣,这里有一个多么有趣的详细解释!看来你对lib很熟悉,我现在才知道。除了众所周知的白方问题,你认为它是成熟的吗?@Wolf谢谢,我也刚刚开始学习SFML。Sprite的内部纹理引用只是一个原始指针常量纹理*m_纹理,造成了所有的麻烦,我们需要保持纹理的生命周期。请阅读您的答案,它也有很好的解释+1您是否知道在一些SFML错误报告中是否已经解决了这一问题?我的意思是,我们看到文档没有告诉人们什么不该做。至少应该为sf:Sprite做私有拷贝,当然最好实现拷贝…我试图找到一个but报告,但是什么都没有。也许不复制是出于性能原因?使用TextureManager似乎很有趣,下面是一个有趣的例子
#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

#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);
}


#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

#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);
}
#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
#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();
}