[英]White square SFML
我在嘗試顯示帶紋理的按鈕時遇到了 SFML C++ 的白色方塊問題。 我有一個繼承自Button.h
的ImageButton.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();
}
截屏
您和其他人( 在 reddit 、 SO和其他地方)面臨的問題是由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.