2016-04-30 62 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