Use an QObject found by it's QObjectName - qt

I have a little problem in my program. I have a config file put in settings. I pull from it the names of the object I need to be checked (these are QCheckBox).
I have this piece of code (It compiles and runs but when it's at "cBox->setChecked" it just crash):
void Preproc::on_tBtnManual_toggled(bool checked){
if(checked){
ui->tBtnManual->setText("Systematic");
}else{
ui->tBtnManual->setText("Manual");
settings.beginGroup("Preprocessing");
QStringList keys = settings.childKeys();
foreach(QString configParam,keys){
QCheckBox *cBox = ui->gridLayout->findChild<QCheckBox *>(configParam);
cBox->setChecked(settings.value(configParam).toBool());
}
}
}
I have tried to put ui->cBox->... put it says that cBox is not a child of ui.
If I qDebug(cBox) I have a QObject(0x0) so nothing !
I'm a little new to Qt so maybe it's a simple thing.
Thanks and have a nice day :)

Are you sure that an object is found?
I don't think so (different name? wrong layout?). cBox is 0x0 when nothing is found.
However put a
if (cBox)
before
cBox->setChecked(settings.value(configParam).toBool());
and it will not crash anymore when it doesn't find an object by name.

are you sure the name (content of configParam) is correct?
you can try the search from QApplication
QApplication::instance()->findChild<QCheckBox *>(configParam);
the findChild method performs a recursive search, if the object exists in the hirachie, it will be found. if the object is not found, it could be:
the object does not exist
the object has another name
the object or one of its ancestors has no (NULL) parent
can you post the part of the .ui file with the check box? it would be helpful.

Related

How to pass a QTextEdit to signal/slot mechanism

I have read some topics here about signals and slots and its parameters but found nothing about following problem:
I am working with Qt 5.7
I simply have 2 classes, inside 1st, I want to emit signal with string message and location(or specific object) where to display it.
Now it is like this: I have 1st class where I emit signal :
emit signalWriteToTextEdit("hallo","textEdit_3");
What I want to do is somehow pass as the second argument an object like textEdit. No QString as its now.
Inside 2nd class is the slot:
void writeToTextEdit(QString info, QString where){
where.append(info); //I would like to do something like this
}
Just dont know how to consider that second parameter "where" as accessible object for example textEdit, so I could change its content.
I am thinking also if this is possible:
Is there some method for Ui object like finding elements by name?
Is it possible to go with foreach over all elements in ui and check their names...? I tried but dont know how to go through that.
If its not clear, I will explain more
After a little digging, I came across the QObject::findChild function. This will allow a string lookup recursively through the UI, those I am unsure of performance.
Edit for more detail:
Returns the child of this object that can be cast into type T and that is called name, or 0 if there is no such object. Omitting the name argument causes all object names to be matched. The search is performed recursively.
If there is more than one child matching the search, the most direct
ancestor is returned. If there are several direct ancestors, it is
undefined which one will be returned. In that case, findChildren()
should be used.
Just use QWidget* or QObject* (if it is not always a widget) as the argument type
signals:
void writeToTextEdit(const QString &what, QWidget *where)
or if it is always a QTextEdit even more specifically
signals:
void writeToTextEdit(const QString &what, QTextEdit *where)
Though it is not clear why the code needs to emit a signal if it has access to the target object, it could simply call setText directly

crash after QGraphicsProxyWidget is removed from a scene

I have a simple scene with a QGraphicsProxyWidget added to it ( and some widget set on it ).
If I try removing it from the scene, like so:
if ( widget )
{
parentScene->removeItem( m_widget ); // m_widget is a QGraphicsProxyWidget
delete m_widget; // I also tried m_widget->deleteLater() here - same result
m_widget = NULL;
}
I get an instant crash - no descriptive callstack though that would tell me what's wrong ( some windows related calls in the callstack, and that's all ).
I'm using version 5.1.1 of the Qt library, I've searched the manual and the net for an instruction how to actually remove such a widget, and it's not documented at all, so I'm not sure if I'm doing something wrong there, or is there a bug in the library.
I'd appreciate any help.
Cheers,
Piotr
Check your if statement: It says widget when you probably meant m_widget. If widget is non-null and m_widget is null, your program will crash, since the calls to removeItem/delete will attempt to reference a null pointer.
I found the problem - seemingly unrelated call to 'prepareGeometryChange' was to blame here.
My widgets were changing size ( I didn't mention it, 'cause it seemed irrelevant at the time ). However I was calling the aforementioned method AFTER I made the change to the geometry, not before, as the manual instructs.
Apparently that method is very important in order to keep the scene's internal data in order, and due to my calling it incorrectly, it was leaving some invalid references to the deleted items.

SEGFAULT when passing QString by refernce to library function

I've been fighting with this all day long and I've tried passing a QString, a std::string, and a char* in many many different fashions, but if I pass it so that I can modify the parameter's value inside the library function then it SEGFAULTs. If I copy the library function, line for line, into the main app, I can pass references all day long as params and change their values inside the functions.
Here is the stripped down version of my function inside the library.
I have literally removed all code except for this line.
MySQLLib::ExecuteQuery(const QString& query, QString& results)
{
results = "Changed the value of this parameter.";
}
Here is the calling code from the main application.
bmdbTest is an instance of the above MySQLLib class...
All the other code in my library and application works. It just won't let me pass references to ANYTHING to my library.
MySQLProj::pbExecuteQuery_Click()
{
QString x = "Hello.";
bmdbTest->ExecuteQuery("SELECT ttid from test_table", x);
ui_MySQLProj1.textEdit->setText(x);
}
It SEGFAULTs on the bmdbTest->ExecuteQuery call.
I've even tried a simple int& as a parameter with no success.
I can however pass params as const QString& without issue. I just can't modify the param's value that way.
EDIT: I just figured it out. Thank you to "paxdiablo" for suggesting I check my variables for null or invalid pointers. I was really tired last night and I can't believe I missed this.
I just found the problem and I feel like a complete idiot. You mentioned about bmdbTest being null or invalid. The value of bmdbTest was fine as all my other functions worked fine, but when I was calling ExecuteQuery() I was passing the query string from the value in a QLineEdit from my GUI window like this.
bmdbTest->ExecuteQuery(leQuery->text(), resultString);
The leQuery->Text() was actually the problem as I must access leQuery like this.
bmdbTest->ExecuteQuery(ui_MySQLProj1.leQuery->text(), resultString);
You may want to check the value of bmdbTest itself. It may be null or an invalid pointer.
That seems to be indicated by the fact it's faulting on that line. If there were something suspect about the parameters, I would expect it to fault within the ExecuteQuery function.
You should be able to find out exactly where the crash is by putting suitable debug statements (with flushing) on either side of the results = ... and bmdbTest->ExecuteQuery(...) lines (or use a debugger if you have one).

Error with sequence argument when using QtConcurrent map

I'm trying to use QtConcurrent::map to run this function
//This function is used through QtConcurrent::map to create images from a QString path
void MainWindow::createQImage(QString* path) {
//create an image from the given path
QImage* t = new QImage(*path);
imageList->append(t);
}
on this container/sequence (declared in the mainwindow header and initialized in the mainwindow constructor)
QList<QImage *> *imageList = new QList<QImage *>;
Here's the code I'm trying to run
QFutureWatcher<void> futureWatcher;
futureWatcher.setFuture(QtConcurrent::map(imageList, &MainWindow::createQImage));
and here are the errors I'm getting:
request for member 'begin' in 'sequence', which is of non-class type 'QList<QImage*>*'
request for member 'end' in 'sequence', which is of non-class type 'QList<QImage*>*'
I need the "createQImage" function to be run for every element in "imageList," which can reach into the thousands. I believe the problem to be with the first parameter to the map function. And from what I've read, it may have to do with compatibility. There isn't much sample code online that I was able to relate to. I'm new to Qt and not the most experienced of programmers but I'd appreciate some help and feedback.
Alternatively, is there better way to do this using QtConcurrent?
Thanks in advance!
QtConcurrent::map wants a sequence as its first argument. You passed it a pointer to a sequence.
If you do
futureWatcher.setFuture(QtConcurrent::map(*imageList, &MainWindow::createQImage));
it should be happy.
Note that the compiler was reasonably clear about what the problem was. Take the time to read the errors carefully, they're usually not as cryptic as they perhaps at first seem. In this case it was telling you that the argument you passed was not of a class type. A quick look at the argument type at the end of the error reveals that it is a pointer.
QList, QImage, QString are Copy-On-Write types (see other Qt implicitly shared types), so you shouldn't use pointers to these types because they are basically already smart pointers.
And if you remove all pointers from your code, it should also fix the main problem.

QPlainTextEdit segmentation fault

I have some Qt application with QPlainTextEdit in Tab widget. When try to make a pointer on it
QPlainTextEdit *w = (QPlainTextEdit*)ui->tabWidget->widget(0)
and call a document() method
w->document()
I get a segfault.
But if i call document directly, e.g. ui->mainEdit->document(), then everything works fine.
Can anybody explain me why it happens?
You want to do:
QPlainTextEdit *w = ui->mainEdit;
Then w->document() will return what you want. You are getting the segmentation fault because when you cast ui->tabWidget->widget(0); gives a pointer to a tab page object. When you cast this to QPlainTextEdit* are telling your program to treat a part of memory that does not represent a QPlainTextEdit as a QPlainTextEdit. This causes trouble at the time that you call w->document() because that is in the memory location that it tries to access is not what it would expect from memory which belongs to QPlainTextEdit.
i'm almost sure, that ui->tabWidget->widget(0) return container widget inside of tabWidget. Try qDebug() << ui->tabWidget->widget(0)->metaObject()->className() and see what is printed. It's probably just "QWidget" not "QPlainTextEdit". Your edit is inside of layout of this widget
You can use qobject_cast to make sure that it returns the right type.
QPlainTextEdit *w = qobject_cast<QPlainTextEdit*>(ui->tabWidget->widget(0));
if (w)
{
...
}
It'll return 0 if the type is not of QPlainTextEdit*.
As stated, widget(0) is probably not returning what you wanted - and probably contains a container or some other item, and is probably not the way you want to be accessing your widgets unless there is no other way.

Resources