我想写一个程序,允许用户使用鼠标绘制。我一直在尝试很多不同的方法来使用sf::RenderWindow
的对象来适当地更新显示器,以致无法成功地调用display()
。我正在发生绘制的循环是调用显示如此之快,导致大量闪烁(通过测试证实)。如果我添加一种方法来减慢对display()
的呼叫,如使用sf::Clock
,则只会在与display()
相同的延迟上更新绘图,从而导致口吃效应。我需要的是一种更新显示器的方式,足以显示绘图更新,同时不会导致屏幕闪烁。RenderWindow不断更新显示()导致闪烁
目前,我已经有了一个延迟(在事件轮询switch语句的底部)显示屏幕,以便闪烁不会发生,但加入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);
}
好吧,我只是想画当用户按住鼠标左键时。我没有清理窗口,因为我想绘制多个圆圈以允许用户像绘画程序那样制作一个形状。无论如何,窗口仍然闪烁,因为显示过于频繁。 – Acejhm
您需要清除,绘制和显示每个循环迭代。如果您想保留之前绘制的内容,请记住数据(例如圆形矢量)并在每次迭代中绘制它们。 – nvoigt
@nviogt我会说实话,我没有想到会工作,但它的确如此。谢谢。现在我很好奇,为什么在显示之前不清除屏幕导致了这一点。我认为这就像更新功能。无论如何,我感谢帮助。 – Acejhm