2017-07-26 82 views
0

我真的很困擾這個奇怪的bug一段時間。即使在顯示小部件之前,我的應用程序也會崩潰(但顯示窗口本身)。這裏是我的代碼:Qt5 C++應用程序崩潰原因不明

的main.cpp

#include "mainwindow.h" 
#include <QApplication> 
#include <QTimer> 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    MainWindow w; 
    w.setWindowTitle("Snake"); 
    w.resize(500, 500); 
    w.show(); 
    QTimer* timer = new QTimer(); 
    while(!w.checkCollision()) 
    { 
     if(timer -> isActive() == false) 
     { 
      w.play(); 
      timer -> start(1); 
     } 
    } 
    return a.exec(); 
} 

mainwindow.h

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 

#include <QMainWindow> 
#include <QPainter> 
#include <QKeyEvent> 
#include <QDebug> 
#include <snakeclass.h> 

namespace Ui { 
class MainWindow; 
} 

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = 0); 
    Snake snake; 
    void paintEvent(QPaintEvent*); 
    void keyEvent(QKeyEvent* keyevent); 
    void move(); 
    bool checkCollision(); 
    void play(); 
    ~MainWindow(); 

private: 
    Ui::MainWindow *ui; 
}; 

#endif // MAINWINDOW_H 

mainwindow.cpp

#include "mainwindow.h" 
#include "ui_mainwindow.h" 
#include <QPainter> 
#include <QPainterPath> 
#include <QKeyEvent> 

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent), 
    ui(new Ui::MainWindow) 
{ 

} 

void MainWindow::paintEvent(QPaintEvent*) 
{ 
    QPainter painter(this); 
    // Draw black background. 
    painter.drawRect(0, 0, 500, 500); 
    painter.fillRect(0, 0, 500, 500, Qt::black); 
    for(unsigned int i = 0; i < snake.getLength(); i++) 
    { 
     // Draw green snake's body. 
     painter.setPen(Qt::green); 
     painter.setBrush(Qt::green); 
     // If i = 0, so if we are drawing snake's head. 
     if(i == 0) 
     { 
      // Draw red head. 
      painter.setPen(Qt::red); 
      painter.setBrush(Qt::red); 
     } 
     painter.drawEllipse((snake.getDot(i)).x, (snake.getDot(i)).y, 10, 10); 
    } 
} 

void MainWindow::keyEvent(QKeyEvent* keyevent) 
{ 
    if(keyevent -> key() == Qt::Key_Left) 
    { 
     if(snake.getDirection() != Snake::Direction::RIGHT) 
     { 
      snake.setDirection(Snake::Direction::LEFT); 
     } 
    } 
    else if(keyevent -> key() == Qt::Key_Right) 
    { 
     if(snake.getDirection() != Snake::Direction::LEFT) 
     { 
      snake.setDirection(Snake::Direction::RIGHT); 
     } 
    } 
    else if(keyevent -> key() == Qt::Key_Up) 
    { 
     if(snake.getDirection() != Snake::Direction::DOWN) 
     { 
      snake.setDirection(Snake::Direction::UP); 
     } 
    } 
    else if(keyevent -> key() == Qt::Key_Down) 
    { 
     if(snake.getDirection() != Snake::Direction::UP) 
     { 
      snake.setDirection(Snake::Direction::DOWN); 
     } 
    } 
} 

void MainWindow::move() 
{ 
    for(unsigned int i = snake.getLength(); i > 0; i--) 
    { 
     snake.editDot((snake.getDot(i - 1)).x, (snake.getDot(i - 1)).y, i, (snake.getDot(i - 1)).direction); 
    } 
    if(snake.getDirection() == Snake::Direction::UP) 
    { 
     if(int(snake.getDot(0).y - 10) < 0) 
     { 
      snake.editDot((snake.getDot(0)).x, 500, 0, snake.getDirection()); 
     } 
     else 
     { 
      snake.editDot((snake.getDot(0)).x, (snake.getDot(0)).y - 10, 0, snake.getDirection()); 
     } 
    } 
    else if(snake.getDirection() == Snake::Direction::DOWN) 
    { 
     if(((snake.getDot(0)).y + 10) > 490) 
     { 
      snake.editDot((snake.getDot(0)).x, 0, 0, snake.getDirection()); 
     } 
     else 
     { 
      snake.editDot((snake.getDot(0)).x, (snake.getDot(0)).y + 10, 0, snake.getDirection()); 
     } 
    } 
    else if(snake.getDirection() == Snake::Direction::RIGHT) 
    { 
     if(((snake.getDot(0)).x + 10) > 490) 
     { 
      snake.editDot(0, (snake.getDot(0)).y, 0, snake.getDirection()); 
     } 
     else 
     { 
      snake.editDot((snake.getDot(0)).x + 10, (snake.getDot(0)).y, 0, snake.getDirection()); 
     } 
    } 
    else if(snake.getDirection() == Snake::Direction::LEFT) 
    { 
     if((int((snake.getDot(0)).x) - 10) < 0) 
     { 
      snake.editDot(500, (snake.getDot(0)).y, 0, snake.getDirection()); 
     } 
     else 
     { 
      snake.editDot((snake.getDot(0)).x - 10, (snake.getDot(0)).y, 0, snake.getDirection()); 
     } 
    } 
} 

bool MainWindow::checkCollision() 
{ 
    for(unsigned int i = 0; i < snake.getLength(); i++) 
    { 
     for(unsigned int j = 0; j < snake.getLength(); j++) 
     { 
      if((i != j) && ((snake.getDot(i)).x == (snake.getDot(j)).x) && ((snake.getDot(i)).y == (snake.getDot(j)).y)) 
      { 
       return true; 
      } 
     } 
    } 
    return false; 
} 

void MainWindow::play() 
{ 
    //move(); 
    update(); 
} 

MainWindow::~MainWindow() 
{ 
    delete ui; 
} 

snakeclass.h

#ifndef SNAKECLASS 
    #define SNAKECLASS 

    #include <vector> 

    class Snake 
    { 
     public: 

      enum class Direction 
      { 
       LEFT, 
       RIGHT, 
       UP, 
       DOWN 
      }; 

      // Dot is a part of the snake. 
      struct dot 
      { 
       unsigned int x; 
       unsigned int y; 
       // Number of the dot (head is 0). 
       unsigned int dotNumber; 
       // Direction of the particular dot. 
       Direction direction; 
      }; 

      unsigned int getLength(); 
      unsigned int getScore(); 
      unsigned int getSpeed(); 
      Direction getDirection(); 
      dot getDot(unsigned int dotNumber); 

      void setLength(unsigned int length); 
      void setScore(unsigned int score); 
      void setSpeed(unsigned int speed); 
      void setDirection(Direction direction); 
      // Returns new dot's dotNumber. 
      unsigned int newDot(); 
      void editDot(unsigned int x, unsigned int y, unsigned int dotNumber, Direction direction); 

     private: 

      unsigned int length = 3; 
      unsigned int score = 0; 
      unsigned int speed = 1; 
      Direction direction = Direction::RIGHT; 
      std::vector <dot> dots = {dot {250, 250, 0, Direction::RIGHT}, 
             dot {240, 250, 1, Direction::RIGHT}, 
             dot {230, 250, 2, Direction::RIGHT}}; 
    }; 

    #endif // SNAKECLASS 

snakeclass.cpp

#include "snakeclass.h" 

unsigned int Snake::getLength() 
{ 
    return length; 
} 

unsigned int Snake::getScore() 
{ 
    return score; 
} 

unsigned int Snake::getSpeed() 
{ 
    return speed; 
} 

Snake::Direction Snake::getDirection() 
{ 
    return direction; 
} 

Snake::dot Snake::getDot(unsigned int dotNumber) 
{ 
    return dots.at(dotNumber); 
} 

void Snake::setLength(unsigned int length) 
{ 
    this -> length = length; 
} 

void Snake::setScore(unsigned int score) 
{ 
    this -> score = score; 
} 

void Snake::setSpeed(unsigned int speed) 
{ 
    this -> speed = speed; 
} 

void Snake::setDirection(Snake::Direction direction) 
{ 
    this -> direction = direction; 
} 

unsigned int Snake::newDot() 
{ 
    dot newDot; 
    newDot.dotNumber = dots.size(); 
    dots.push_back(newDot); 
    length ++; 
    return newDot.dotNumber; 
} 

void Snake::editDot(unsigned int x, unsigned int y, unsigned int dotNumber, Snake::Direction direction) 
{ 
    for(unsigned int i = 0; i < dots.size(); i++) 
    { 
     if((dots.at(i)).dotNumber == dotNumber) 
     { 
      dots.at(i).x = x; 
      dots.at(i).y = y; 
      dots.at(i).direction = direction; 
     } 
    } 
} 

我是新來QT5,這是我參與的畫家和鍵盤事件的第一個項目。你能幫我弄清楚上面代碼中的問題是什麼嗎?謝謝你所有的答案!

+0

你有什麼信息嗎?嘗試從命令行啓動程序。你可能會看到一些。另外,如果你在unix平臺上(linux,OSX),你可以嘗試在[valgrind](http://valgrind.org/)中運行它。 – litelite

+0

你是否錯過了'setupUi(this)'調用? – drescherjm

+0

堆棧跟蹤在哪裏? – MrEricSir

回答

1

即使在顯示小部件之前(但顯示窗口本身),我的應用程序仍會崩潰。

它不會崩潰。在main.cpp有一個無限循環,其中有一些結果是預期的,即!w.checkCollision(),但由於沒有事件循環在main.cpp中運行,所以沒有任何反應,程序在那裏等待是徒勞的。

作爲一個回答你的問題,爲了看小部件以下列方式增加QApplication::processEvents();

while(!w.checkCollision()) 
{ 
    QApplication::processEvents(); 

    if(timer -> isActive() == false) 
    { 
     w.play(); 
     timer -> start(1); 
    } 
} 

然而,用這種方法,你將面臨更多的問題。所以我強烈建議你看看Qt Creator中的例子,看看Qt開發人員認爲使用庫的正確方式。

+0

@FilipMirosław,作爲一個額外的建議,你不需要比較條件語句中布爾變量的值,也就是說,最好使用if(!timer-> isActive())而不是' if(timer-> isActive()== false)'。 – scopchanov

+0

你是對的這個!我非常需要一些專業的例子。另外,你能推薦一些Qt5書籍嗎? –

+0

這對我來說依然是一個謎,爲什麼widgets不顯示。調用paintevent的w.show()在無限循環之前被調用。另外爲什麼它是無限循環?據我所知checkCollision()會在某個時候返回true。 –

相關問題