RenderWindow不断更新display()导致闪烁

RenderWindow Constantly Updating display() Causing Flickering

我正在尝试编写一个允许用户使用鼠标绘图的程序。我一直在尝试许多不同的方法来使用 sf::RenderWindow 的对象来适当地更新显示以调用 display() 但没有太大成功。我正在绘图的循环正在快速调用显示,导致大量闪烁(通过测试确认)。如果我添加一种方法来减慢对 display() 的调用,例如使用 sf::Clock,那么绘图只会在与 display() 相同的延迟上更新,从而导致断断续续的效果。我需要的是一种足够频繁地更新显示以显示绘图更新同时又不会导致屏幕闪烁的方法。

目前,我已经延迟显示(在事件轮询开关语句的底部),因此不会发生闪烁,但是将 mainWindow.display(); 添加到 void MainWindow::draw() 函数会导致因为更新太快而闪烁。我在 sf::Event::MouseMoved 上绘制了绘图,但我尝试更改它以查看是否有帮助,但没有。

这里是所有绘图和事件检测发生的地方:

MainWindow.h

#pragma once
#include "GraphPaper.h"
#include "stdafx.h"

class MainWindow
{
    public:
        MainWindow(short, short);
        void close();
        void start();
        void moveCamera(sf::Keyboard::Key);
        void draw(sf::Event);
        void displayWindow(sf::Vector2i&);

    private:
        bool leftMousePressed, rightMousePressed, isExiting;
        int r, g, b, mouseX, mouseY;
        short height, width;

        const short DRAWING_CRICLE_RADIUS = 10;

        GraphPaper paper;
        //DrawingBrush brush;

        const sf::Color WHITE = sf::Color(255, 255, 255);
        const sf::Color BLACK = sf::Color(0, 0, 0);

        sf::CircleShape circle;
        sf::Mouse cursor;
        sf::Vector2i windowCenter;
        sf::RenderWindow mainWindow;
        sf::View view;
};

MainWindow.cpp:

#include "MainWindow.h"
#include "GraphPaper.h"
#include "stdafx.h"

MainWindow::MainWindow(short height, short width)
{
    this->height = height;
    this->width = width;
    circle.setRadius(DRAWING_CRICLE_RADIUS);
    circle.setFillColor(BLACK);
}

void MainWindow::start()
{
    sf::Clock clock;
    mainWindow.create(sf::VideoMode(height, width, 32), "Test");

    sf::View view(sf::FloatRect(0,0,height,width));
    mainWindow.setView(view);

    leftMousePressed, rightMousePressed, isExiting = false;

    sf::Event currentEvent;
    sf::Vector2i windowCenter(mainWindow.getPosition().x + (mainWindow.getSize().x / 2), mainWindow.getPosition().y + (mainWindow.getSize().y / 2));

    displayWindow(windowCenter);

    while (!isExiting)
    {
        sf::Clock clock;
        while (mainWindow.pollEvent(currentEvent))
        {
            switch (currentEvent.type)
            {
            case sf::Event::MouseMoved:
            {
                if (rightMousePressed == true)
                {
                    std::cout << "Mouse Panned\n";
                }
                if (leftMousePressed == true)
                {
                    draw(currentEvent);
                }
                break;
            }
            case sf::Event::MouseButtonPressed:
            {
                std::cout << "Mouse Pressed\n";

                mouseX = currentEvent.mouseButton.x;
                mouseY = currentEvent.mouseButton.y;

                if (currentEvent.mouseButton.button == sf::Mouse::Left)
                {
                    while (currentEvent.type != sf::Event::MouseButtonReleased)
                    {
                        std::cout << "Mouse is Drawing\n";
                        draw(currentEvent);
                        mainWindow.pollEvent(currentEvent);
                    }
                }
                else if (currentEvent.mouseButton.button == sf::Mouse::Right)
                {
                    rightMousePressed = true;
                }
                break;
            }
            case sf::Event::MouseButtonReleased:
            {
                std::cout << "Mouse Released\n";
                if (currentEvent.mouseButton.button == sf::Mouse::Left)
                {
                    leftMousePressed = false;
                }
                else if(currentEvent.mouseButton.button == sf::Mouse::Right)
                {
                    rightMousePressed = false;
                }
                break;
            }
            case sf::Event::KeyPressed:
            {
                sf::Keyboard::Key keyPressed = currentEvent.key.code;
                if(keyPressed == sf::Keyboard::Escape)
                {
                    close();
                }
                else if(keyPressed == sf::Keyboard::Left || sf::Keyboard::Right ||
                                       sf::Keyboard::Down || sf::Keyboard::Up ||
                                       sf::Keyboard::A || sf::Keyboard::S ||
                                       sf::Keyboard::D || sf::Keyboard::W)
                {
                    moveCamera(keyPressed);
                    displayWindow(windowCenter);
                }
                break;
            }
            case sf::Event::Closed:
            {
                close();
                break;
            }
            case sf::Event::Resized:
            {
                windowCenter = sf::Vector2i(mainWindow.getPosition().x + (mainWindow.getSize().x / 2), mainWindow.getPosition().y + (mainWindow.getSize().y / 2));
                displayWindow(windowCenter);
                break;
            }
            }
            if (clock.getElapsedTime().asMilliseconds() >= 500)
            {
                clock.restart();
                mainWindow.display();
            }
        }
    }
}
void MainWindow::moveCamera(sf::Keyboard::Key keyPressed)
{
    view = mainWindow.getView();
    switch (keyPressed)
    {
    case sf::Keyboard::A:
    case sf::Keyboard::Left:
    {
        view.move(-50, 0);
        break;
    }
    case sf::Keyboard::D:
    case sf::Keyboard::Right:
    {
        view.move(50, 0);
        break;
    }
    case sf::Keyboard::W:
    case sf::Keyboard::Up:
    {
        view.move(0, 50);
        break;
    }
    case sf::Keyboard::S:
    case sf::Keyboard::Down:
    {
        view.move(0, -50);
        break;
    }
    }
    mainWindow.setView(view);
}
void MainWindow::draw(sf::Event mouse)
{
    circle.setPosition(mainWindow.mapPixelToCoords(sf::Vector2i(mouse.mouseMove.x, mouse.mouseMove.y)));
    mainWindow.draw(circle);
}
void MainWindow::close()
{
    std::cout << "Closing...\n";
    mainWindow.close();
    isExiting = true;
}
void MainWindow::displayWindow(sf::Vector2i& windowCenter)
{
    mainWindow.clear(WHITE);
    mainWindow.draw(paper.getSprite());
    mainWindow.display();
    cursor.setPosition(windowCenter);
}

您遗漏了渲染循环的一个重要部分。您应该在每次循环迭代时绘制所有零件。现在你只画你的圆当它改变时。

您的代码应如下所示:

  1. 根据输入更改圆圈位置
  2. 清楚window
  3. 画圆
  4. 显示