Использование qpropretyanimation желательно

В этой программе я построил QPropertyanimation и добавить к нему мой товар и pos() имущество. Я переопределяю KeyPressEvent, И с использованием ключей, состоящих из J, F, Z пункт идут forward,идти back а также jump,

В зависимости от силы тяжести, когда предмет прыжок должен упасть. Для этого я звоню down функция. Но предмет только один раз прыгает, не упадет. У меня также есть еще одна проблема: когда при первом нажатии кнопки j и f (вперед и назад) желательно анимировать, но в следующий раз элемент переместится вперед и вернется ко всей сцене.

Я имею в виду, что он должен быть анимирован, например, 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();
}

1 ответ

Решение

Вы не должны использовать resize а также setFixedSize на view потому что вы используете его в 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();
}
Другие вопросы по тегам