QTimer不会提前屏幕

时间:2014-03-08 19:30:06

标签: c++ qt qgraphicsscene qtimer

我在dialog.cpp中创建了我的场景,并在我的scene.cpp中绘制了一些QGraphicsItem。当我将我的QTimer添加到我的dialog.cpp时,只要我将光标移动到场景上就会崩溃。

dialog.cpp

#include "dialog.h"
#include "scene.h"
#include "ui_dialog.h"
#include "instructions.h"
#include "settings.h"
#include "highscore.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);

    // Create and configure scene
     scene = new Scene;
     scene->setBackgroundBrush(Qt::black);
     scene->setItemIndexMethod(QGraphicsScene::NoIndex);
     ui->graphicsView->setScene(scene);
     scene->setSceneRect(-200, -150, 400, 300);
     ui->graphicsView->setMouseTracking(true);

     QPixmap tankbase1(":/images/tankbase.jpg");
     ui->tankbaseplay1->setPixmap(tankbase1);

//\/\/\/This is my problem. And not sure why\/\/\/\/\/\/
//     timer = new QTimer(this);
//     QObject::connect(timer, SIGNAL(timeout()), scene, SLOT(advance()));
//     timer->start(10);

}

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

//void Dialog::shoot()
//{

//}


void Dialog::on_startButton_clicked()
{
    ui->settingsButton->hide();
    ui->titlescreen->hide();
    ui->highscoreButton->hide();
    ui->instructionButton->hide();
    ui->startButton->hide();

    QGraphicsTextItem *FirstP;
    QString P1 = "Player1";
    FirstP = scene->addText(P1);
    FirstP->setFont(QFont("Nimbus Mono L", 12,QFont::Bold));
    FirstP->setDefaultTextColor(Qt::white);
    FirstP->setPos(-300, -220);


    QGraphicsTextItem *SecondP;
    QString P2 = "Player2";
    SecondP = scene->addText(P2);
    SecondP->setFont(QFont("Nimbus Mono L", 12,QFont::Bold));
    SecondP->setDefaultTextColor(Qt::white);
    SecondP->setPos(230, -220);
}

void Dialog::on_instructionButton_clicked()
{
    Instructions intDialog;
    intDialog.setModal(true);
    intDialog.exec();
}

void Dialog::on_settingsButton_clicked()
{
    settings intDialog;
    intDialog.setModal(true);
    intDialog.exec();
}


void Dialog::on_highscoreButton_clicked()
{
    highscore intDialog;
    intDialog.setModal(true);
    intDialog.exec();
}

scene.cpp

#include "scene.h"
#include <QGraphicsEllipseItem>
#include <QGraphicsLineItem>
#include <QGraphicsSceneMouseEvent>
#include <QTimer>
#include "qmath.h"
#include <math.h>




class GraphicsCircle : public QGraphicsEllipseItem
// class for the fire bullets
{
public:
    GraphicsCircle(qreal dirx, qreal diry)
        : m_Speed(3)
        , m_DirX(dirx)
        , m_DirY(diry)
    {
        setRect(-3.0,-3.0,8.0,8.0);
        setPos(-195, 130);
        QRadialGradient rGrad( 0.0, 0.0, 20.0, 0.0, 0.0);
        rGrad.setColorAt(0.0, QColor(255,255,255));
        rGrad.setColorAt(0.7, QColor(255,255,225));
        rGrad.setColorAt(1.0, QColor(255,0,0,0));
        setBrush(QBrush(rGrad) );
        setPen(QPen(Qt::NoPen));
    }

    virtual ~GraphicsCircle() {}

    void advance(int phase)
    {
        if(!phase) return;
        setPos(x()+m_Speed*m_DirX, y()+m_Speed*m_DirY);
    }

private:
    qreal m_Speed;
    qreal m_DirX;
    qreal m_DirY;
};

Scene::Scene() : QGraphicsScene()
{
    // added the lines below to setup an item, pointing in the positive x direction
    int x1 = 0;
    int y1 = 0;
    cannon = new QGraphicsLineItem(x1, y1, x1 + 50, y1);
    cannon->setPen(QPen(Qt::white, 6));
    this->addItem(cannon);
    cannon->setPos(-195, 130);

    //Create bullets
    m_FireTimer= new QTimer();
    QObject::connect(m_FireTimer, SIGNAL(timeout()), this, SLOT(fire()));
}

void Scene::mousePressEvent(QGraphicsSceneMouseEvent *e)
{
    m_FireTarget = e->scenePos();
    m_FireTimer->start();
    QGraphicsScene::mousePressEvent(e);
}

void Scene::mouseMoveEvent(QGraphicsSceneMouseEvent *e)
{
//    emit mouseMoving(e->scenePos());
//    FirstPlayer->setPos(e->scenePos());

//    qAtan2(cannon->pos(), e->scenePos());

    m_FireTarget = e->scenePos();
    QGraphicsScene::mouseMoveEvent(e);

    QLineF arm(cannon->pos(), e->scenePos());
    cannon->setRotation(360 - arm.angle());


}

void Scene::mouseReleaseEvent ( QGraphicsSceneMouseEvent * e )
{
    m_FireTimer->stop();
    QGraphicsScene::mouseReleaseEvent(e);
}

void Scene::fire()
// creates a fire bullet
// the bullet will move in the direction of the mouse cursor
// the trajectory is sligthly perturbated by a random small angle
{
    qreal dirx = m_FireTarget.x()-195;
    qreal diry = m_FireTarget.y()-195;

    qreal length = sqrt(dirx*dirx+diry*diry);
    if (length!=0)
    {
        // normalized direction vector
        qreal invLength= 1.0/length;
        dirx *= invLength;
        diry *= invLength;

        // creating an angle perturbation of +/- 3°
        qreal alphaPerturbation = static_cast<qreal>(qrand()%6-3) * M_PI / 180.0;
        qreal xPerturbation = cos(alphaPerturbation);
        qreal yPerturbation = sin(alphaPerturbation);
        dirx = dirx*xPerturbation - diry*yPerturbation;            
        diry = diry*xPerturbation + dirx*yPerturbation;

        GraphicsCircle * circle = new GraphicsCircle(dirx, diry);
        addItem(circle);

    }
}

void Scene::advance()
{
   // first remove the pellet out of the sceneRect
    for (int i=0; i<items().count(); ++i)
    {
        QGraphicsItem * item = items().at(i);
        qreal x= item->x();
        qreal y= item->y();
        qreal sx=sceneRect().width();
        qreal sy= sceneRect().height();
        if ( (x < 0.0) || (y < 0.0) || (x > sx) || (y > sy))
        {
            removeItem(item);
            delete item;
        }
    }
    QGraphicsScene::advance();
}

当我在dialog.cpp中运行没有QTimer代码的代码时,它会运行并显示我的QGraphicsItems并相应地移动。当我添加QTimer时,QGraphicsItem消失。完全失去了问题所在。

此外,我已经拍摄了场景代码,并单独运行它,它的工作原理。唯一的区别是场景和QCimer是在main.cpp中创建的。

非常需要帮助!!!!!

1 个答案:

答案 0 :(得分:0)

在删除列表中的项目时,您正在遍历项目列表。这听起来很麻烦。

http://qt-project.org/doc/qt-5/qrect.html#intersects

http://qt-project.org/doc/qt-5/qgraphicsitem.html#boundingRect

http://qt-project.org/doc/qt-5/qrectf.html#contains

我认为您的advance()功能可能会更清晰。

QList <QGraphicsItem *> itemsToRemove;
foreach( QGraphicsItem * item, this->items() )
{
    if( !this->sceneRect().intersects(item->boundingRect()) )
    {
        // The item is no longer in the scene rect, get ready to delete it
        itemsToRemove.append(item);
    }
}

foreach( QGraphicsItem * item, itemsToRemove )
{
    this->removeItem(item);
    delete(item);
}

另请阅读QGraphicsScene的描述,

http://qt-project.org/doc/qt-5/qgraphicsscene.html#details

有许多辅助方法可以使查找某个区域中的项目或一个项目与另一个项目发生冲突更加容易。

希望有所帮助。