#c #qt #paint
#c #qt #Краски
Вопрос:
я думаю о том, чтобы написать примитивную змею. у меня есть окно, в котором программа рисует случайные строки.
но я не могу придумать, как поймать нажатую клавишу, чтобы изменить направление нарисованной линии.
class QUpdatingPathIte : public QGraphicsPathItem
{
void advance(int phase)
{
if (phase == 0)
return;
int x,y;
int w,a,s,d;
char c;
//
// HOW TO MAKE THIS HERE? (i had done early in console application)
// but i can't do this in GUI , what should i do?
scanf("%c",amp;c);
if (c=='w')
{ x=-20; y=0; }
else if (c=='s')
{ x=20; y=0; }
else if (c=='a')
{ x=0; y=-20; }
else if(c=='d')
{ x=0; y=20; }
QPainterPath p = path();
p.lineTo(x, y);
setPath(p);
}
};
#include <QtGui/QApplication>
#include "dialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene s;
QGraphicsView v(amp;s);
QUpdatingPathIte item;
item.setPen(QPen(QColor("black")));
s.addItem(amp;item);
v.show();
QTimer *timer = new QTimer(amp;s);
timer->connect(timer, SIGNAL(timeout()), amp;s, SLOT(advance()));
timer->start(500);
return a.exec();
}
Ответ №1:
QGraphicsView наследует от от QWidget, потому что он наследует от QAbstractScrollArea. Вы должны создать пользовательский подкласс QGraphicsView и просто переопределить функцию keyPressEvent(). Пример:
class SnakeView : public QGraphicsView
{
protected:
keyPressEvent(QKeyEvent *e)
{
// Do something
// Otherwise pass to the graphics view
QGraphicsView::keyPressEvent(e)
}
};
Тогда вместо создания объекта QGraphicsView вы бы создали объект SnakeView.
Комментарии:
1. Другой способ сделать это без создания подклассов — установить фильтр событий. Смотрите
QObject::installEventFilter()
.
Ответ №2:
QGraphicsView переопределяет keyPressEvent и перенаправляет события в QGraphicsScene. QGraphicsScene поддерживает нажатия клавиш через свой обработчик keyPressEvent. По умолчанию QGraphicsScene перенаправит это нажатие клавиши на текущий QGraphicsItem через свою функцию keyPressEvent.
Учитывая вышесказанное, то, что вы, вероятно, хотите сделать, это переопределить keyPressEvent
обработчик в вашем QUpdatingPathItem
:
void QUpdatingPathItem::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Key::Key_A: /* do something useful */; break;
case Key::Key_S: /* do something useful */; break;
case Key::Key_W: /* do something useful */; break;
case Key::Key_D: /* do something useful */; break;
}
}
Я не смог толком понять, что вы пытались сделать в вашем advance
методе, поэтому я не могу многое предложить в виде предлагаемого обработчика.
Помимо реализации QObject::installEventFilter, вы также можете создать подкласс любого из QGraphicsView, QGraphicsScene или QGraphicsItem и переопределить функцию keyPressEvent.
Ответ №3:
спасибо вам всем. Тогда я не достиг своей цели. Но время шло, и я пришел к той же проблеме, и теперь я ее решил.
Есть правильные и достойные ответы, но тогда я был недостаточно хорош, чтобы собрать их вместе, потому что ни один из них не был полным и достаточным. Теперь я сделал это так:
HEADER FILE "header.h"
class MyGraphicView: public QGraphicsView
{
Updating *m_update;
public:
MyGraphicView(Updating *update);
void keyPressEvent(QKeyEvent *event);
};
#include "header.h"
void GraphicView::keyPressEvent(QKeyEvent *event)
{
switch ( event->key())
{case Qt::Key_Up:
m_update->move_up();
break;
case Qt::Key_Down:
m_update->move_down();
break;
case Qt::Key_Left:
{ m_update->move_right();
break;
}
case Qt::Key_Right:
{ m_update->move_left();
break;
}
}
}
Еще раз спасибо!
Комментарии:
1. Я думаю, что ответ CD1212 правильный (хотя не все детали прописаны)?
Ответ №4:
Ваш выбор QGraphicsView
не очень удачен.
В принципе, когда вы внедряете какой-либо пользовательский графический элемент (графическая область игры — это это), вы должны создать свой собственный виджет и просто реализовать QWidget::keyPressEvent()
метод.
Комментарии:
1. Я должен не согласиться. QGraphicsScene amp; QGraphicsView в значительной степени предназначены для такого рода вещей. Есть много других способов сделать это, помимо отказа от предоставленной ими функциональности.