c++ - QTimer 不会前进屏幕

标签 c++ qt qgraphicsscene qtimer

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

对话框.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();
}

场景.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 消失了。完全迷失了问题所在。

另外,我已经获取了场景代码并单独运行它并且它有效。唯一的区别是场景和 QTimer 是在 main.cpp 中创建的。

急需帮助!!!!!!

最佳答案

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

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

有许多辅助方法可以更轻松地查找某个区域中的项目或一个项目与另一个项目的碰撞。

希望对您有所帮助。

关于c++ - QTimer 不会前进屏幕,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22273982/

相关文章:

c++ - 如何使用动态数组制作 pop_front

c++ - shared_ptr 与 QThreadPool

c++ - 如何实现显示对象属性的系统//构建游戏引擎

c++ - 如何使 QGraphicsItem 的位置依赖于另一个 QGraphicsItem?

c++ - QTreeView 与 setIndexWidget

c++ - Visual Studio 2008 Profiler - Instrumented 产生奇怪的结果

c++ - dlsym() + RTLD_NEXT 在 Ubuntu 20.04 上无法正常工作

c++ - 使用 stackBefore 更改 QGraphicsItem 堆栈顺序

qt - 在 QGraphicsView 的 ScrollHandDrag 模式下,如何停止 QGraphicsItems 在场景中的移动?

python-2.7 - 这是 PyQt 4 python 错误还是行为错误的代码?