QLineEdit combined with QStackedWidget, crash
-
@jsulm this is just a demo, the code is very simple, just a QLineEdit, a QStackedWidget and a QPushButton. And it crashed necessarily in running mode, while it didn't crash in debugging mode. I think this is a Qt's bug since the code is too simple and it crashed necessarily.
-
@Wenchi said in QLineEdit combined with QStackedWidget, crash:
I think this is a Qt's bug since the code is too simple and it crashed necessarily
Before claiming there is a bug in Qt you should find out where and why it crashes.
Please take a look at the output of your app: there are many many on_lineEdit_textChanged calls - what does it do (post its code)? I guess @J-Hilk is right and you have an endless loop... -
@jsulm Here I post the whole code. As you can see I didn't change the lineEdit's text, I still don't understand why there're so many lineEdit_textChanged calls. I can only tell that changing the stackedWidget's current index is the reason which causes so many lineEdit_textChanged calls.
#include "mainwindow.h" #include "./ui_mainwindow.h" #include <QDebug> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); ui->stackedWidget->setCurrentIndex(0); connect(ui->lineEdit,&QLineEdit::textChanged,this,[this](const QString &tex){ lineEdit_textChanged(tex); }); } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_pushButton_clicked() { qDebug()<< ui->lineEdit->text(); //ui->lineEdit->setText(ui->lineEdit->text()); } void MainWindow::lineEdit_textChanged(const QString &arg1) { qDebug()<<"on_lineEdit_textChanged"<<arg1; //ui->lineEdit->blockSignals(true); ui->stackedWidget->setCurrentIndex(1); //ui->lineEdit->blockSignals(false); }
-
@Wenchi
You don't say, but I assume thatui->lineEdit
is on stacked widget #0 and there is a another, different page at stacked widget #1?You might get some indication what is going on if you place a breakpoint at the start of
lineEdit_textChanged()
and look at the stack trace as it keeps getting hit. You should also look at the stack trace when it "crashes". -
@Wenchi
So thelineEdit
is not on either of the stacked widget pages --- how would we ever have known this? The stacked widget just has two blankQWidget
s in it.OK. But what about using the debugger as everyone is saying to see what is going on?
Meanwhile: do you just type in
test
once? Because everything looks like you are appendingtest
to the line edit ontextChanged()
signal somewhere? Use that debugger to see.... -
@JonB
I insert a break point, and have clicked "run" for 3 times.
Then I canceled the breakpoint and run. The stack overflowed and it crashed.
By the way, just intput sth by Chinese input method, and don't press "Enter" to make it finish. -
Wow, surprisingly I can reproduce that even in debug mode. This does seem to have some bug caused by repeatly gaining and losing focus.
Only need to type one "test" then output endless[debug]MainWindow::on_lineEdit_textChanged(126):on_lineEdit_textChanged "test" [debug]MainWindow::on_lineEdit_textChanged(126):on_lineEdit_textChanged "testtest" [debug]MainWindow::on_lineEdit_textChanged(126):on_lineEdit_textChanged "testtesttest" [debug]MainWindow::on_lineEdit_textChanged(126):on_lineEdit_textChanged "testtesttesttest" [debug]MainWindow::on_lineEdit_textChanged(126):on_lineEdit_textChanged "testtesttesttesttest" [debug]MainWindow::on_lineEdit_textChanged(126):on_lineEdit_textChanged "testtesttesttesttesttest" [debug]MainWindow::on_lineEdit_textChanged(126):on_lineEdit_textChanged "testtesttesttesttesttesttest"
But I haven't got time to debug it through yet.
-
@Wenchi
If @Bonnie is on it (a) I would guess he is not using "Chinese input method", so that's not it, and (b) he will track it down!But just so I understand (because I do not). You write "under the Chinese input method ", but I don't know what that is/how it works. Do I take it that it shows you that "bar" of possible inputs (numbered 1 to 7), you click on
1 test
and that insertstest
into the line edit, just once? Since I assume @Bonnie has reproduced without that it does not seem relevant, but I would like to understand.If you look carefully at your stack trace you can see that
lineEdit_textChanged()
is indeed calling itself recursively, as suspected, hence the eventual "crash".Meanwhile, I would guess --- bug or not --- that there is something "wrong" with "changing focus while you are inside the
textChanged()
signal handler", something assumes the focus will not change from theQLineEdit
it is currently handling. And that somehow makes it keep "re-seeing" the same originaltest
input and adding it. If this is so, you may have to do theui->stackedWidget->setCurrentIndex(1);
call from aQTimer::singleShot()
you set off in your slot.... -
@JonB
First allow me to explain the "Chinese input method":
When I input "test":
Then I can click "1"(or "2" or "3"...) or press "Enter" and the input is finished and this status won't cause crash:
If I click somewhere else, the input is not finished and this status can cause crash:
To fix this problem, I add the code "blockSignals":void MainWindow::lineEdit_textChanged(const QString &arg1) { qDebug()<<"on_lineEdit_textChanged"<<arg1; ui->lineEdit->blockSignals(true); ui->stackedWidget->setCurrentIndex(1); ui->lineEdit->blockSignals(false); }
-
@Wenchi
OK, now I know (a bit) about how "Chinese input" works! But I suspect this itself is not the issue, assuming @Bonnie is reproducing the issue.I am not a great fan of
blockSignals()
, one is never sure what the side-effects ignoring signals might be. Given that I suggested thatQLineEdit
might not having like focus changed while insidetextChanged()
signal, what about theQTimer
alternative I suggested instead of blocking signals:QTimer::singleShot(0, [this]() { ui->stackedWidget->setCurrentIndex(1); });
-
@JonB said in QLineEdit combined with QStackedWidget, crash:
If @Bonnie is on it (a) I would guess he is not using "Chinese input method", so that's not it, and (b) he will track it down!
No, I'm using it actually :)
I've done debugging.
BecauseQStackedWidget::setCurrentIndex
callsQWidget::clearFocus
which makes the window to emit afocusObjectChanged
signal (no matter it actually had the focus or not).
And during the application handling that, it finds the input method composing, so it send aQInputMethodEvent
bysendEvent
to commit the string and end the composition after that.
But while the line edit handling the event, it emitstextChanged
again so that never ends.
Not sure whether that is a bug or not...Maybe we are just not supposed to change focus withintextChanged()
-
@Bonnie said in QLineEdit combined with QStackedWidget, crash:
No, I'm using it actually :)
Oh! @Bonnie does not sound like a very Chinese name :)
Maybe we are just not supposed to change focus within
textChanged()
That is evidently the case. For whatever reason, it appears the internals expect the line edit to have the focus while dealing with
textChanged()
, and changing it causes the signal to be re-emitted.