Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: serg_hd от Июнь 25, 2011, 17:53



Название: [решено] QLineEdit returnPressed()
Отправлено: serg_hd от Июнь 25, 2011, 17:53
Проблема, на первый взгляд, пустяковая. Есть класс (содержит gui), наследник QWidget'a, в нём кнопка и текстовое поле. При нажатии на кнопку шлётся сигнал по которому этот класс зачищается родительским. Захотел то же самое сделать для текстового поля:
Код
C++ (Qt)
QObject::connect(this->ui->btnOk, SIGNAL(pressed()), SIGNAL(accept()));
QObject::connect(this->ui->leCount, SIGNAL(returnPressed()), SIGNAL(accept()));
 

При испускании сигнала accept() сам класс зачищается. Проблема в том, что если нажимать кнопку - всё ок, форма закрывается и чистится (у родителя этот класс в QScopedPointer'е). Но если нажать Enter на поле ввода, то в 70% случаев - segfault, но иногда тоже всё норм. Казалось бы, какие могут быть проблемы, когда оба сигнала - и кнопка и поле ввода соединены с одним и тем же сигналом класса. Пробовал также перед зачисткой ставить фокус на родительском виджете, не помогает (обычно из-за фокуса бывают такие проблемы, если его не сбрасывать перед зачисткой). Совершенно непонятно в чём причина...


Название: Re: QLineEdit returnPressed()
Отправлено: Disaron от Июнь 25, 2011, 19:00
Чисто предположение: может returnPressed() соединен по дефолту с чем-то еще, и это что-то следует отсоединить предварительно?
А то мало ли что там connectSlotsByName() и иже с ним натворит.
Я бы попробовал проэкспериментировать так :
Код
C++ (Qt)
QObject::connect(this->ui->leCount, SIGNAL(returnPressed()), this->ui->btnOk, SIGNAL(pressed()));


Название: Re: QLineEdit returnPressed()
Отправлено: serg_hd от Июнь 25, 2011, 20:23
Чисто предположение: может returnPressed() соединен по дефолту с чем-то еще, и это что-то следует отсоединить предварительно?
А то мало ли что там connectSlotsByName() и иже с ним натворит.
Я бы попробовал проэкспериментировать так :
Код
C++ (Qt)
QObject::connect(this->ui->leCount, SIGNAL(returnPressed()), this->ui->btnOk, SIGNAL(pressed()));
пробовал, изначально именно так и делал


Название: Re: QLineEdit returnPressed()
Отправлено: LisandreL от Июнь 25, 2011, 20:31
попробуйте для этого сигнала тип коннекта Qt::QueuedConnection поставить. Может там в функции, вызывающей сигнал ещё после него обращения к объектам идёт и из-за тог, что они уже не существуют всё накреняется.


Название: [решено] QLineEdit returnPressed()
Отправлено: serg_hd от Июнь 25, 2011, 22:04
попробуйте для этого сигнала тип коннекта Qt::QueuedConnection поставить. Может там в функции, вызывающей сигнал ещё после него обращения к объектам идёт и из-за тог, что они уже не существуют всё накреняется.
Проканало, благодарствую. Но всё равно не понимаю почему так работает. Если бы знал, что QLineEdit завязан на момент испускания сигнала с кем-то ещё, то и сам изначально этот тип сигнала бы указал. Но ведь ни он, ни qpushbutton, к которому этот же слот вешаю (без queuedconnection и работает) ни с кем больше не завязаны.
Кстати, valgrind ругался:
Код:
Invalid read of size 4
at 0x04c2b2cd: QMetaObject::activate(QObject*, QMetaObject const*, int, void**) (in /usr/lib/libQtCore.so.4.7.2)
by 0x0485b706: QLineControl::editingFinished() (in /usr/lib/libQtGui.so.4.7.2)
by 0x045d2498: QLineControl::processKeyEvent(QKeyEvent*) (in /usr/lib/libQtGui.so.4.7.2)
by 0x045c65e7: QLineEdit::keyPressEvent(QKeyEvent*) (in /usr/lib/libQtGui.so.4.7.2)
Address 0x9458894 is 4 bytes inside a block of size 132 free'd
at 0x04025907: operator
by 0x0485bb81: ??? (in /usr/lib/libQtGui.so.4.7.2)
by 0x045cd4af: ??? (in /usr/lib/libQtGui.so.4.7.2)
by 0x04c2d3ef: QObject::~QObject() (in /usr/lib/libQtCore.so.4.7.2)



Название: Re: [решено] QLineEdit returnPressed()
Отправлено: LisandreL от Июнь 26, 2011, 00:43
Проканало, благодарствую. Но всё равно не понимаю почему так работает. Если бы знал, что QLineEdit завязан на момент испускания сигнала с кем-то ещё, то и сам изначально этот тип сигнала бы указал.
Если посмотреть исходники, то внутри QLineEdit используется QLineControl.

Код
C++ (Qt)
   if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
       if (hasAcceptableInput() || fixup()) {
           emit accepted();
           emit editingFinished();
       }
       if (inlineCompletionAccepted)
           event->accept();
       else
           event->ignore();
       return;
   }

emit accepted(); - реэмитится в QLineEdit::returnPressed(), а emit editingFinished() - в QLineEdit::editingFinished().

Таким образом при прямом соединении весь последующий код выполняется уже по разрушенным обектам:
Цитировать
    if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
        if (hasAcceptableInput() || fixup()) {
            emit accepted();
            emit editingFinished();
        }
        if (inlineCompletionAccepted)
            event->accept();
        else
            event->ignore();
        return;
    }
что черевато.


Название: Re: [решено] QLineEdit returnPressed()
Отправлено: serg_hd от Июнь 26, 2011, 03:41
до просмотра исходников реализации QLineEdit'а доходить не решился, но со стороны его разработчиков не упомянуть такого в документации (рекомендацию использовать queuedconnection при сигнале returnPressed()), по-моему, не есть хорошо.


Название: Re: [решено] QLineEdit returnPressed()
Отправлено: BRE от Июнь 26, 2011, 04:09
до просмотра исходников реализации QLineEdit'а доходить не решился, но со стороны его разработчиков не упомянуть такого в документации (рекомендацию использовать queuedconnection при сигнале returnPressed()), по-моему, не есть хорошо.
Просто не стоит в слотах разрушать объект инициирующий выполнение этого слота! Для этого лучше воспользоваться специальным методом deleteLater().