C++ 按Qt键

C++ 按Qt键,c++,qt,paint,C++,Qt,Paint,我想到了写原始蛇。我有一个程序画随机线的窗口 但我想不出如何抓住按下的键来改变画线的方向 class QUpdatingPathIte : public QGraphicsPathItem { void advance(int phase) { if (phase == 0) return; int x,y; int w,a,s,d; char c; //

我想到了写原始蛇。我有一个程序画随机线的窗口

但我想不出如何抓住按下的键来改变画线的方向

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",&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(&s);

    QUpdatingPathIte item;
    item.setPen(QPen(QColor("black")));
    s.addItem(&item);
    v.show();

    QTimer *timer = new QTimer(&s);
    timer->connect(timer, SIGNAL(timeout()), &s, SLOT(advance()));
    timer->start(500);

    return a.exec();
}

class-qpdatingpathite:public-QGraphicsPathItem
{
无效提前(int阶段)
{
如果(相位==0)
返回;
int x,y;
int w、a、s、d;
字符c;
// 
//如何在这里做到这一点?(我在控制台应用程序早期就做过)
//但我不能在GUI中执行此操作,我应该怎么做?
scanf(“%c”、&c);
如果(c=='w')
{x=-20;y=0;}
else如果(c=='s')
{x=20;y=0;}
else如果(c=='a')
{x=0;y=-20;}
else如果(c=='d')
{x=0;y=20;}
QPainterPath p=path();
p、 lineTo(x,y);
设置路径(p);
}
};
#包括
#包括“dialog.h”
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
qs;
QGraphicsView v&s;
QUpdatingPathIte项目;
项目.设置笔(QPen(QColor(“黑色”));
s、 附加项(&项);
v、 show();
QTimer*定时器=新的QTimer(&s);
定时器->连接(定时器、信号(timeout())、&s、插槽(advance());
定时器->启动(500);
返回a.exec();
}

您选择的
QGraphicsView
不是很幸运


基本上,当您实现一些自定义绘制的图形项目(游戏的图形区域就是这个)时,您应该创建自己的小部件,只需实现
QWidget::keyPressEvent()
方法。

QGraphicsView继承自QWidget,因为它继承自QBStractScrollArea。您应该创建QGraphicsView的自定义子类,只需重写函数keyPressEvent()。例如:

class SnakeView : public QGraphicsView
{
protected:
    keyPressEvent(QKeyEvent *e)
    {
         // Do something

         // Otherwise pass to the graphics view
         QGraphicsView::keyPressEvent(e)
    }
};

然后,您将创建SnakeView对象,而不是创建QGraphicsView对象。

QGraphicsView重新实现并将事件转发到QGraphicsCenter。QGraphicscene通过其处理程序支持按键。默认情况下,QGraphicscene将通过其功能将按键转发到当前QGraphicsItem

鉴于上述情况,您可能需要在
QUpdatingPathItem
中重新实现
keyPressEvent
处理程序:

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
方法中试图做的事情,因此我无法提供建议的处理程序


除了实现,您还可以对QGraphicsView、QGraphicscene或QGraphicsSitem中的任何一个进行子类化,并覆盖keyPressEvent函数。

谢谢大家。然后我没有达到我的目标。但随着时间的推移,我遇到了同样的问题,现在我解决了

有正确和有价值的答案,但我没有足够好地把它们放在一起,因为没有人是充分和充足的。现在我这样做了:

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;
}
}

}


再次感谢

另一种不用子类化的方法是安装事件过滤器。请参见
QObject::installEventFilter()
。我一定不同意。qgraphicscene和QGraphicsView非常适合这种类型的东西。除了放弃其提供的功能外,还有许多其他方法可以做到这一点。我认为CD1212的答案是正确的(尽管并没有详细说明所有细节)?