1

在这个程序中,我构建了一个QPropertyanimation并将我的项目和pos()属性添加到它。我覆盖KeyPressEvent. 并使用由j, f, zitem go forward, goback和组成的键jump

根据物品跳跃时的重力应该下落。为此,我称之为down函数。但是项目只跳一次就不会掉。我还有另一个问题:当第一次按下jf(前进和后退)项目动画时很理想,但下一次项目前进并返回所有场景。

我的意思是它应该动画,例如 40 像素,但它动画 800 像素。

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    QPoint start;
    QPoint end;
    ~MainWindow();
private:
    QGraphicsView* view;
    QGraphicsScene* scene;
    void keyPressEvent(QKeyEvent* k);
    MyQgraphicsObject* m;
    QPropertyAnimation* pr;
    QElapsedTimer* timer;
    int f;
    int u;
    int b;
    void forward();
    void up();
    void back();
    void down();
};

MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent)
{
    view=new QGraphicsView;
    scene=new QGraphicsScene;
    m=new MyQgraphicsObject;
    pr=new QPropertyAnimation(m,"pos");
    view->setScene(scene);
    view->resize(800,800);
    view->setFixedSize(800,800);
    setCentralWidget(view);
    scene->addItem(m);
    start= QPoint(0,0);
    f=30;
    u=-30;
    b=-30;
}

void MainWindow::keyPressEvent(QKeyEvent *k)
{
    switch (k->key()) {
    case Qt::Key_J: {
        forward();
        break;
        }
   case Qt::Key_Z: {
        up();
        down();
        break;
        }
   case Qt::Key_F: {
        back();
        break;
        }
   default:
        break;
   }
}

void MainWindow::forward()
{
    end.setX(f);
    pr->setEndValue(end);
    pr->setDuration(1000);
    pr->setEasingCurve(QEasingCurve::Linear);
    pr->start();
    f+=40;
}

void MainWindow::up()
{
    end.setY(u);
    pr->setEndValue(end);
    pr->setDuration(1000);
    pr->setEasingCurve(QEasingCurve::Linear);
    pr->start();
    u-=30;
    pr->pause();
}

void MainWindow::back()
{
    end.setX(b);
    pr->setEndValue(end);
    pr->setDuration(1000);
    pr->setEasingCurve(QEasingCurve::Linear);
    pr->start();
    b-=40;
}

void MainWindow::down()
{
    u+=30;
    end.setY(u);
    pr->setEndValue(end);
    pr->setDuration(1000);
    pr->setEasingCurve(QEasingCurve::Linear);
    pr->start();
}
4

1 回答 1

2

你不应该使用resizeand setFixedSizeonview因为你使用它setCentralWidget并且它的大小将由布局管理。您应该setFixedSize在主窗口上使用。

动画是异步的。例如,当您调用 时up(); down(),这些函数将在没有 1 秒暂停的情况下执行。此外,已经开始的动画也没有效果。

通常,当您确切知道下一秒需要对象移动的位置时,就会以这种方式使用动画。当动画已经执行时,接收来自用户的指令并改变对象的轨迹是很复杂的。

这是一个示例,显示了正确使用此任务的动画。对象每秒可以接收一个指令(前进、后退或跳跃),并在下一秒执行相应的动画。

标题:

class MainWindow : public QMainWindow {
  Q_OBJECT      
public:
  explicit MainWindow(QWidget *parent = 0);
  ~MainWindow();
private:
  QGraphicsView* view;
  QGraphicsScene* scene;
  void keyPressEvent(QKeyEvent* k);
  QGraphicsObject* object;
  QPropertyAnimation* animation;
  QPointF pos;
  double speed;

  enum Command {
    command_none, command_jump, command_forward, command_back
  };
  Command next_command;

private slots:
  void timeout();
};

来源:

MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent)
{
  view = new QGraphicsView;
  scene = new QGraphicsScene;
  object = scene->addWidget(new QPushButton("test"));
  object->setPos(0, -object->boundingRect().height());
  animation = new QPropertyAnimation(object,"pos");
  animation->setDuration(1000);
  view->setScene(scene);
  setFixedSize(800,800);
  scene->addRect(-500, -200, 1000, 200);
  setCentralWidget(view);
  scene->addItem(object);
  next_command = command_none;
  speed = 100;

  QTimer* timer = new QTimer(this);
  connect(timer, SIGNAL(timeout()), this, SLOT(timeout()));
  timer->start(1000);
}

MainWindow::~MainWindow() {}

void MainWindow::keyPressEvent(QKeyEvent *k)
{
  switch (k->key()) {
  case Qt::Key_J: {
    next_command = command_forward;
    break;
  }
  case Qt::Key_Z: {
    next_command = command_jump;
    break;
  }
  case Qt::Key_F: {
    next_command = command_back;
    break;
  }
  default:
    break;
  }
}

void MainWindow::timeout() {
  //fall
  if (pos.y() < 0) {
    pos.setY(pos.y() + speed);
    if (pos.y() >= 0) {
      pos.setY(0);
    }
  }
  //action
  switch(next_command) {
  case command_forward:
    pos.setX(pos.x() + speed);
    break;
  case command_back:
    pos.setX(pos.x() - speed);
    break;
  case command_jump:
    if (pos.y() == 0) {
      pos.setY(pos.y() - speed);
    }
    break;
  default:
    break;
  }
  next_command = command_none;
  animation->stop();
  animation->setEndValue(pos - QPointF(0, object->boundingRect().height()));
  animation->start();
}
于 2014-07-01T13:33:23.070 回答