2017-07-26 4 views
0

Ich kämpfe seit einiger Zeit mit diesem seltsamen Bug. Meine Anwendung stürzt ab, noch bevor Widgets angezeigt werden (aber das Fenster selbst wird angezeigt). Hier ist mein Code:Qt5 C++ - Anwendung Abstürze aus unbekannten Gründen

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; 
     } 
    } 
} 

Ich bin neu in QT5 und dies ist mein erstes Projekt Maler und Tastaturereignissen mit einbezieht. Könnten Sie mir helfen, herauszufinden, was das Problem im obigen Code ist? Danke für alle Antworten!

+0

Haben Sie eine Nachricht? Versuchen Sie, Ihr Programm über die Befehlszeile zu starten. Sie könnten einige sehen. Wenn Sie sich auf einer Unix-Plattform (Linux, OSX) befinden, können Sie auch versuchen, sie in [valgrind] (http://valgrind.org/) auszuführen. – litelite

+0

Fehlt Ihnen ein 'SetupUi (this) 'Anruf? – drescherjm

+0

Wo ist der Stack-Trace? – MrEricSir

Antwort

1

Meine Anwendung stürzt ab, noch bevor Widgets angezeigt werden (aber das Fenster selbst wird angezeigt).

Es stürzt nicht ab. In main.cpp gibt es eine Endlosschleife, in der einige Ergebnisse erwartet werden, nämlich !w.checkCollision(), aber da in main.cpp keine Ereignisschleife läuft, passiert nichts und die Programme hängen dort vergeblich.

Als Antwort auf Ihre Frage, um die Widgets hinzufügen QApplication::processEvents(); in der folgenden Art und Weise, um zu sehen:

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

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

jedoch bei diesem Ansatz finden Sie weitere Probleme. Daher rate ich Ihnen dringend, sich die Beispiele im Qt Creator anzuschauen, um zu sehen, welche die richtige Art ist, die Bibliothek zu verwenden, wie von den Qt-Entwicklern gedacht.

+0

@Filip Mirosław, als zusätzlichen Ratschlag, müssen Sie nicht den Wert einer booleschen Variablen in einer bedingten Anweisung vergleichen, dh es ist besser, 'if (! Timer-> isActive())' anstelle von 'zu verwenden if (timer-> isActive() == false) '. – scopchanov

+0

Sie haben Recht mit diesem! Ich brauche wirklich ein professionelles Beispiel. Kannst du auch einige Qt5-Bücher empfehlen? –

+0

Es ist mir immer noch ein Rätsel, warum Widgets nicht zeigen. w.show() welcher Aufruf paintevent wird vor einer Endlosschleife aufgerufen. Auch warum ist es Endlosschleife? Soweit ich weiß, wird checkCollision() irgendwann wieder korrekt sein. –

Verwandte Themen