【问题标题】:I get just black screen in an SFML sf::RenderWindow我在 SFML sf::RenderWindow 中只看到黑屏
【发布时间】:2016-12-20 00:21:14
【问题描述】:

我尝试在一个 c++ windows 窗体项目(这里也是新的 :D)中使用 SFML 的优点(我还是新手)。我的想法是当事件发生时,此 SFML 窗口会弹出显示图像。我已经设法让 SFML 窗口在事件发生时弹出,但它只出现在空白屏幕上,但没有显示我想要的纹理......这是涉及 SFML 的代码摘录,带有 "// 。 ." 我会删掉不必要的代码:

BatteryAlarmDlg.h

class CBatteryAlarmDlg : public CDialog
{
    // ... 
    protected:
    // ...

    // timers
    Timer m_tPowerCheck; // the struct Timer has just two members - int id and int duration
    Timer m_tWindowRefresh;

    // sounds
    sf::SoundBuffer m_sfsbWarningMessageBuffer;
    sf::Sound m_sfsWarningMessageSound;
    std::string m_sPathToWarningMessageSoundFile;

    // sfml window management support
    sf::RenderWindow m_sfwChangePowerMessage;
    sf::Texture m_sftChangePowerMessage;
    sf::RectangleShape m_sfrChangePowerMessage;
    bool m_bIsWindowAlive;
    sf::Event m_sfeEvent;

    // ...
};

在上面的代码中,我只是声明了成员。

BatteryAlarmDlg.cpp

// ...
BOOL CBatteryAlarmDlg::OnInitDialog()
{
    // ...
    /// init timers ///
    m_tPowerCheck = Timer(42, 1000); // a timer with id == 42 and with a duration == 1,000 ms
    SetTimer(m_tPowerCheck.id, m_tPowerCheck.duration, nullptr);
    m_tWindowRefresh = Timer(1, 15);
    SetTimer(m_tWindowRefresh.id, m_tWindowRefresh.duration, nullptr);

    /// init sounds ///
    m_sPathToWarningMessageSoundFile = "warning-message-2.wav";
    if (!m_sfsbWarningMessageBuffer.loadFromFile(m_sPathToWarningMessageSoundFile))
    {
        MessageBox("Error loading of warning message sound file!");
    }
    m_sfsWarningMessageSound.setBuffer(m_sfsbWarningMessageBuffer);

    /// init messages windows ///
    m_sfwChangePowerMessage.setFramerateLimit(60);
    if (!m_sftChangePowerMessage.loadFromFile("ChagePowerMessage.png"))
    {
        MessageBox("Error loading of warning message image file!");
    }
    m_sfrChangePowerMessage.setSize
        (
            sf::Vector2f(m_sfwChangePowerMessage.getSize().x, m_sfwChangePowerMessage.getSize().y)
        );

    m_sfrChangePowerMessage.setPosition(0, 0);
    m_sfrChangePowerMessage.setTexture(&m_sftChangePowerMessage);
    m_bIsWindowAlive = false;

    return TRUE;  // return TRUE  unless you set the focus to a control
}
    // ...
void CBatteryAlarmDlg::OnTimer(UINT_PTR nIDEvent)
{
    if (nIDEvent == m_tPowerCheck.id)
    {

        if (GetSystemPowerStatus(&m_spsPower) == 0)
        {
            // message = "Error: Could not get the system power status!";
            MessageBox("Error: Could not get the system power status!");
        }       
        if (m_spsPower.ACLineStatus == 0 & m_iPowerChange == 1)
        {
            if (!m_sfwChangePowerMessage.isOpen())
            {
                m_sfwChangePowerMessage.create(sf::VideoMode(800, 600), "Battery allarm : System Power Changed!");
            }
            m_sfwChangePowerMessage.clear();
            m_sfwChangePowerMessage.draw(m_sfrChangePowerMessage);
            m_sfwChangePowerMessage.display();
            m_iPowerChange = 0;
            m_sfsWarningMessageSound.play();
            m_bIsWindowAlive = true;
        }

        if (m_spsPower.ACLineStatus == 1 & m_iPowerChange == 0)
        {
            m_iPowerChange = 1;
        }

    }


    if (nIDEvent = m_tWindowRefresh.id)
    {
        if (m_bIsWindowAlive)
        {
            while (m_sfwChangePowerMessage.pollEvent(m_sfeEvent))
            {
                if
                    (
                        m_sfeEvent.type == sf::Event::Closed ||
                        (m_sfeEvent.type == sf::Event::KeyPressed && m_sfeEvent.key.code == sf::Keyboard::Escape)
                    )
                {
                    m_bIsWindowAlive = false;
                }
            }

            m_sfwChangePowerMessage.clear();
            m_sfwChangePowerMessage.draw(m_sfrChangePowerMessage);

            m_sfwChangePowerMessage.display();
        }

        if(!m_bIsWindowAlive && m_sfwChangePowerMessage.isOpen())
        {
            m_sfwChangePowerMessage.close();
        }
    }
    CDialog::OnTimer(nIDEvent);
}

背后的基本思想是如果有一个事件并且第一个计时器(m_tPowerCheck 每 1 秒)用完,然后显示绘制图像的 SFML 窗口,然后播放声音。 每 15 毫秒 (m_tWindowRefresh) 检查 sfml 窗口是否打开并重绘图片 - 在这里我不确定是否有必要,因为这是一张静止图像,但最初我认为黑屏是因为我不刷新它不断地。但仍然 - 只有黑屏...:\

编辑:SFML 的声音效果很好。

【问题讨论】:

  • 调试程序的第一步:create a mcve.
  • 你能告诉我CDialog::OnTimer(nIDEvent);调用到底用来做什么,看起来像不定式递归调用。还告诉我们如何调用BOOL CBatteryAlarmDlg::OnInitDialog()void CBatteryAlarmDlg::OnTimer(UINT_PTR nIDEvent)
  • @FotoBlysk,感谢您的提问。正如我上面提到的 - 这是一个 c++ windows 窗体项目。这些方法(几乎)自动生成 - BOOL CBatteryAlarmDlg::OnInitDialog() 通常在窗口对话框出现之前初始化变量。
  • /*继续上面的帖子 - 我不小心按了 Enter*/ 我还添加了 OnTimer() 方法 - 这个想法是当一定的时间通过程序来制作某些东西。 CDialog::OnTimer(nIDEvent);在 OnTimer() 方法的末尾自动添加,我不知道为什么 - 我是 windows 窗体编程的新手。但是所有方法都可以正常工作 - 所有变量都正常初始化。在我决定添加一个 sfml 窗口之前,有一个弹出窗口,它是使用 MessageBox() 方法生成的,它应该在它应该做的时候弹出。现在 - sfml 窗口也会出现。

标签: c++ forms screen sfml


【解决方案1】:

您似乎将sf::RectangleShape m_sfrChangePowerMessage 的大小设置为sf::Vector2f(0,0)。 发生这种情况是因为您调用:

m_sfrChangePowerMessage.setSize
        (
            sf::Vector2f(m_sfwChangePowerMessage.getSize().x, m_sfwChangePowerMessage.getSize().y)
        );

在创建窗口之前:

m_sfwChangePowerMessage.create(sf::VideoMode(800, 600), "Battery allarm : System Power Changed!");

我的示例解决方案是替换

m_sfrChangePowerMessage.setSize
        (
            sf::Vector2f(m_sfwChangePowerMessage.getSize().x, m_sfwChangePowerMessage.getSize().y)
        );

m_sfrChangePowerMessage.setSize(sf::Vector2f(800,600));

您也可能对Observer Pattern 感兴趣,它可能对您的申请有所帮助。

【讨论】:

  • 感谢@FotoBlysk,这解决了我的问题。现在它就像一个魅力。我也会审查您建议的这种模式。
猜你喜欢
  • 1970-01-01
  • 2016-04-23
  • 1970-01-01
  • 1970-01-01
  • 2015-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多