Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt Система рисования. Печать _ QGraphicsView + KeyPress Event

Автор: DerKetzer 6.11.2011, 22:44

Доброго времени суток,
Решил поделать курсач. Для этого выбрал библиотеку QT(раньше с ней дело не имел)...
Пытаюсь создать небольшую игрушку. Для этого использую QPainter + QGraphicsView + QGraphicsScene. Как рисовать я понял... Но как считывать нажатие клавиш?

Код main'a:

int main(int argc, char **argv)
{
     QApplication app(argc, argv);
     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
     QGraphicsScene scene;
     QGraphicsView view;
     for (int i = 0; i < 8; ++i) {
     Tanks *tank= new Tanks;
     scene.addItem(tank);
     }
     view.show();
     return app.exec();
}


Если вставить функцию:

void QGraphicsView::KeyPressEvent(QKeyEvent* event){
    if(event->key()==Qt::Key_W) {
         //Do Smth
    }
}


То при нажатии на 'W' ничего не происходит.

Помогите нубасу пожалуйста! :)

Автор: wiz29 7.11.2011, 12:08

обрисую в общих чертах, как сделать правильно для твоей программы.
Создай класс который будет генерить сигналы нажатия/отжатия кнопок.
Для это в конструкторе класса установи

    if (qApp)
    {
        qApp->installEventFilter(this);
    }


далее в процедуре фильтра событий обрабатывай QEvent::KeyPress и генери сигнал.
выглядеть это будет примерно следующим образом
bool AppKeyHook::eventFilter(QObject* pObj, QEvent* e)
{
    if (pObj)
    {
        if (e->type() == QEvent::KeyPress)
        {
            QKeyEvent* pKeyEv = static_cast<QKeyEvent*>(e);
            if (!pKeyEv->isAutoRepeat())
            {
                std::map<int, bool>::iterator pos = m_keyMap.find(pKeyEv->key());
                if (pos != m_keyMap.end())
                {
                    if (pos->second == false)
                    {
                        pos->second = true;
                        emit KeyPressed(pKeyEv->key());
                    }
                }
                else
                {
                    m_keyMap[pKeyEv->key()] = true;
                    emit KeyPressed(pKeyEv->key());
                }
            }
        }
        else if (e->type() == QEvent::KeyRelease)
        {
            QKeyEvent* pKeyEv = static_cast<QKeyEvent*>(e);            
            if (!pKeyEv->isAutoRepeat())
            {
                std::map<int, bool>::iterator pos = m_keyMap.find(pKeyEv->key());
                if (pos != m_keyMap.end())
                {
                    if (pos->second == true)
                    {
                        pos->second = false;
                        emit KeyReleased(pKeyEv->key());
                    }
                }
                else
                {
                    m_keyMap[pKeyEv->key()] = false;
                    emit KeyReleased(pKeyEv->key());
                }
            }
        }
    }
    return false;
}

все довольно просто

Автор: DerKetzer 7.11.2011, 13:59

Спасибо за скорый ответ.
Такс, создал класс(мб что то не правильно понял):

#include <QGraphicsView>
#include <QObject>

class keyPress
{
public:
    keyPress();
    bool eventFilter(QObject* obj, QEvent* e);
protected:
    void KeyReleased(QKeyEvent* e);
    void KeyPressed(QKeyEvent* e);
    QObject* pObj;
private:
    std::map<int, bool> m_keyMap;
};


реализация:

#include <QMessageBox>
#include <QtCore>
#include <QtGui>

keyPress::keyPress()
{
    if(qApp) qApp->installEventFilter (this);
}

void keyPress::KeyReleased(QKeyEvent* e)
{
    QMessageBox msgBox;
    if(e->key ()==Qt::Key_W) msgBox.setText("bla.");

}

void keyPress::KeyPressed(QKeyEvent* e)
{
    QMessageBox msgBox;
    if(e->key ()==Qt::Key_Z) msgBox.setText("The document has been modified.");
}

bool keyPress::eventFilter(QObject* pObj, QEvent* e)
{
...
}

int main(int argc, char **argv)
{
     QApplication app(argc, argv);
     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
     QGraphicsScene scene;
     QGraphicsView view(&scene);
     keyPress key;
     for (int i = 0; i < 8; ++i) {
         Tanks *tank= new Tanks;
         scene.addItem(tank);
     }
     view.show();
     return app.exec();
}


Наследником чего должен быть класс keyPress? Я так понял, что QGraphicsView... так ли это?

Автор: wiz29 9.11.2011, 8:27

Цитата(DerKetzer @ 7.11.2011, 14:59) *
Наследником чего должен быть класс keyPress? Я так понял, что QGraphicsView... так ли это?


Достаточно унаследоваться от QObject

Автор: DerKetzer 13.11.2011, 5:47

Цитата(wiz29 @ 9.11.2011, 8:27) *
Цитата(DerKetzer @ 7.11.2011, 14:59) *
Наследником чего должен быть класс keyPress? Я так понял, что QGraphicsView... так ли это?


Достаточно унаследоваться от QObject


Спасибо, разобрался)

Автор: Гость 25.1.2012, 9:59

Вопрос почти в тему:
Как подписаться на таймер?

Имеется ввиду, в таких же условиях работы с QGraphicsScene, ну и новичка, в качестве автора.

Автор: ViGOur 25.1.2012, 12:49

QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(processOneThing()));
timer->start();
где processOneThing твоя функция член класса, которая вызывается каждый раз, когда происходит событие таймера...

Смотри: http://doc.crossplatform.ru/qt/4.7.x/qtimer.html#details

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)