2016-04-30 16 views
0

我想写一个程序,允许用户使用鼠标绘制。我一直在尝试很多不同的方法来使用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); 
} 

回答

1

你缺少的渲染循环的重要组成部分。您应该在每个循环迭代中绘制所有部件。现在你只是在改变时画出你的圈子。

您的代码应该是这样的:

  1. 改圈位置,并根据输入
  2. 透明窗口
  3. 平局圈
  4. 显示
+0

好吧,我只是想画当用户按住鼠标左键时。我没有清理窗口,因为我想绘制多个圆圈以允许用户像绘画程序那样制作一个形状。无论如何,窗口仍然闪烁,因为显示过于频繁。 – Acejhm

+0

您需要清除,绘制和显示每个循环迭代。如果您想保留之前绘制的内容,请记住数据(例如圆形矢量)并在每次迭代中绘制它们。 – nvoigt

+0

@nviogt我会说实话,我没有想到会工作,但它的确如此。谢谢。现在我很好奇,为什么在显示之前不清除屏幕导致了这一点。我认为这就像更新功能。无论如何,我感谢帮助。 – Acejhm