Russian Qt Forum
Ноябрь 24, 2024, 15:37 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QKeyEvent и QMainWidget. Проблема получения события главным окном. Помогите плз  (Прочитано 8838 раз)
star62
Гость
« : Декабрь 24, 2008, 11:15 »

Ситуация следующая. Есть главное окно, на нем еще виджеты(QSpinBox). У главного реализован keyPressEvent(QKeyEvent *event), но проблема в том что при старте фокус получают виджеты главного окна и они перехватывают keyPressEvent и не пропускают его до главного окна. Поэтому реализованный keyPressEvent(QKeyEvent *event) не срабатывает пока фокус не получит главное окно. Вариант с перемещением фокуса на главное окно с помощью Tab не нравиться.
Я подозреваю что есть возможность сказать чтобы виджеты передавали keyPressEvent(QKeyEvent *event) до главного окна(которое для них является родителем), но только не знаю как. Подскажите. Или какой другой вариант решения данной проблемы. Вариант переписи виджета так же отпадает.
Записан
Rcus
Гость
« Ответ #1 : Декабрь 24, 2008, 11:23 »

Цитировать
void QObject::installEventFilter ( QObject * filterObj )

Installs an event filter filterObj on this object. For example:

     monitoredObj->installEventFilter(filterObj);
автоматически можно поставить фильтр переопределив функцию
Код
C++ (Qt)
void QObject::childEvent ( QChildEvent * event )
в классе окна
Записан
star62
Гость
« Ответ #2 : Декабрь 24, 2008, 11:50 »

Отличный способ. Спасибо
« Последнее редактирование: Декабрь 24, 2008, 12:26 от star62 » Записан
star62
Гость
« Ответ #3 : Декабрь 24, 2008, 14:28 »

Улыбающийся После детальных разборов все оказалось не так радужно. А может я чего не до конца понял. Но получается так, что
Код:
void QObject::childEvent ( QChildEvent * event )
использовать не получается, так как в нее приходит только 4 события (QEvent::ChildAdded, QEvent::ChildPolished, QEvent::ChildRemoved и 70/его значение не нашел/).

Использование
Код:
void QObject::installEventFilter ( QObject * filterObj )
работает но приходиться это делать всем потомкам главного окна, что так же представляется не очень корректно.

Есть ли способ сделать так чтобы любое событие попадало в первую очередь на главное окно, а от туда уже на нужный объект? Но только чтобы это был метод главного окна. Так сказать прослойка между инициатором события и его получателем.
Записан
BRE
Гость
« Ответ #4 : Декабрь 24, 2008, 14:35 »

Цитата из assistant:
Код
C++ (Qt)
class MainWindow : public QMainWindow
{
public:
    MainWindow();
 
protected:
    bool eventFilter(QObject *obj, QEvent *ev);
 
private:
    QTextEdit *textEdit;
};
 
MainWindow::MainWindow()
{
    textEdit = new QTextEdit;
    setCentralWidget(textEdit);
 
    textEdit->installEventFilter(this);
}
 
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (obj == textEdit) {
        if (event->type() == QEvent::KeyPress) {
            QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
            qDebug() << "Ate key press" << keyEvent->key();
            return true;
        } else {
            return false;
        }
    } else {
        // pass the event on to the parent class
        return QMainWindow::eventFilter(obj, event);
    }
}
 
Записан
star62
Гость
« Ответ #5 : Декабрь 24, 2008, 14:58 »

Я так и зделал. Но это приводит к тому что необходимо каждому потомку установить этот фильтр.
Записан
Rcus
Гость
« Ответ #6 : Декабрь 24, 2008, 15:11 »

Я имел ввиду примерно следующую схему
Код
C++ (Qt)
bool MainWindow::eventFilter(QObject *obj, QEvent *ev)
{
   qDebug("%s, %d",qPrintable(obj->objectName()),ev->type());
   return QMainWindow::eventFilter(obj,ev);
}
 
void MainWindow::childEvent( QChildEvent* e)
{
   switch (e->type())
   {
   case QEvent::ChildAdded:
       e->child()->installEventFilter(this);
       break;
   case QEvent::ChildRemoved:
       e->child()->removeEventFilter(this);
       break;
   default:
       break;
   }
 QMainWindow::childEvent(e);
}
ну или вместо переопределения ::childEvent можно воспользоваться foreach
Записан
ритт
Гость
« Ответ #7 : Декабрь 24, 2008, 15:19 »

только что практически такой же примерчик набивал...не успел

стар, а объясни: на кой ляд нужно перехватывать события в виджетах-редакторах? м.б. тогда и решение найдётся проще...
Записан
star62
Гость
« Ответ #8 : Январь 05, 2009, 13:08 »

Перехват нужен для того чтобы получать события нажатия кнопки... В первом посте все написал. Виджеты-редакторы или какие другие, разницы нет, просто у меня такие используются.  А проблема в том, повторюсь, что, когда приложение запущено, активен(в фокусе) находиться какой-то виджет-потомок главного окна, он перехватывает событие keyPressEvent и в результате главное окно его не получает и должной реакции я не получаю, пока фокус не переместить на главное окно. Да и вообще вариант получения события keyPressEvent главным окном только при условии его активности не очень. Нужно чтобы при нажатии на кнопку клавиатуры происходило нужное действие в не зависимости не от чего.
Записан
Dendy
Гость
« Ответ #9 : Январь 05, 2009, 13:57 »

А вам нужны вполне конкретные клавиши, связанные с определёнными действиями, или вообще заблокировать события клавиатуры для дочерних элементов?
Записан
star62
Гость
« Ответ #10 : Январь 05, 2009, 14:11 »

Мне нужны конкретные клавиши: Key_Right, Key_Left и Key_C
Записан
Dendy
Гость
« Ответ #11 : Январь 05, 2009, 14:31 »

Могу предложить топорный способ:

Код:
Window::Window()
{
    QCoreApplication::instance()->installEventFilter( this );
}

void Window::keyPressEvent( QKeyEvent * e )
{
    qDebug() << "key event:" << e->key();
}

bool Window::eventFilter( QObject * o, QEvent * e )
{
    if ( o->isWidgetType() && (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) )
    {
        QKeyEvent * ke = static_cast<QKeyEvent*>( e );
        QWidget * w = static_cast<QWidget*>( o );
        if ( w != this && isAncestorOf( w ) )
        {
            if ( ke->key() == Qt::Key_C || ke->key() == Qt::Key_Left || ke->key() == Qt::Key_Right )
            {
                QCoreApplication::instance()->sendEvent( this, ke );
                return true;
            }
        }
    }
    return false;
}
Записан
star62
Гость
« Ответ #12 : Январь 05, 2009, 14:43 »

Спасибо.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.121 секунд. Запросов: 21.