I have some code that works but I don't understand the meaning of this pattern:
QWindow * window;
if (window = qobject_cast<QWindow *>(root))
window->show();
qobject_cast is Qt's alternative of dynamic_cast for QObject-based classes. root is a pointer to some object. In your case it probably has QObject* or QWidget* type. However, the code expects that it may in fact be a QWindow* object. qobject_cast checks if the object is an instance of QWindow class or any class inherited from it, and returns 0 if that's not the case. If the check is successful, qobject_cast returns QWindow* pointer to the object, and the code can use it to call QWindow-specific methods that are not available through QObject* or QWidget* pointer.
The code translates to the following pseudo-code:
if (root is an instance of `QWindow` set window to that instance)
show that window;
The qobject_cast works exactly like dynamic_cast, but only applies to QObject-derived classes and works even when runtime type information is not available (e.g. for small builds on MSVC, or on some embedded platforms).
Related
In many cases, QObject::connect() is used as a whole to create a connection of signal and slot, e.g.:
QLabel *label = new QLabel;
QScrollBar *scrollBar = new QScrollBar;
QObject::connect(scrollBar, SIGNAL(valueChanged(int)),
label, SLOT(setNum(int)));
But I have noted there are some cases where the prefix QObject:: can be ommitted. For example, in creating dialogs (with QDialog), connect() can be directly used without the prefix. Is there any other similar situation?
Background: Understanding static member functions
First, let's take a step back and think about static member functions in C++. As an example, suppose we have a class named MyClass, with a static member function named myStaticFunction().
From inside a member function of MyClass (or a subclass of MyClass), there are 3 ways to call the example function:
MyClass::myStaticFunction()
this->myStaticFunction()
myStaticFunction()
However, from outside a member function of MyClass (or a subclass of MyClass), there is only 1 way to call the example function:
MyClass::myStaticFunction()
QObject::connect() is a static member function
For example, in creating dialogs (with QDialog), connect() can be directly used without the prefix.
This has almost nothing to do with creating dialogs at all.
Remember, the QObject class has a static member function called connect()*. Also remember that QDialog is a subclass of QObject.
Therefore, from inside a member function of a QObject subclass, there are 3 ways to call connect():
QObject::connect(...)
this->connect(...)
connect(...)
However, from outside a member function of a QObject subclass (such as in the main() function), there is only 1 way to call connect():
QObject::connect(...)
*To be precise, there are many overloads of connect(), including non-static versions. However, we're only focussing on the static versions.
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
I have a class Subclass, subclassed from QObject. I want to know when the item is deleted, so I connected this slot to the QWidget::destroyed() signal inherited by Subclass. But when I try to cast the argument to with qobject_cast, I get a zero result. The same result obtains from C++'s dynamic_cast. Why?
void MyClass::mySlot( QObject * item )
{
qobject_cast<Subclass*>(item); // returns zero, even though item is a Subclass*
}
The reason is that by the time QObject::destroyed() is emitted, your derived class Subclass has already been destroyed. This is implied by the C++ order of destruction. Also, this question deals with a similar issue.
To get around this, you could either use C-style pointer casting (which is dispreferred), or rewrite your code to use a QObject instead.
Qt4.8.5
QObject::connect(button,SIGNAL(clicked()),label,SLOT(setText("dd"));
The Qt Creator tell me It's wrong . What's the problem ?
That you can't pass arguments in a connect() statement. You need a "trampoline" slot that sets the text of your label (or, in Qt 5, you might choose to use a lambda).
For instance, by using a subclass:
class MyLabel : public QLabel {
Q_OBJECT
public slots:
void setTextToFoo() { setText("foo"); }
};
// ...
connect(button,SIGNAL(clicked()),label,SLOT(setTextToFoo());
It depends what exactly you are trying to achieve, to be honest, the example code you provided is not very functional, is "dd" a particular static value you are using, or potentially some other string? Where does it come from, is it in the scope of the called, or is it sent by the caller, which is the usual practice when sending arguments to slots.
Either way, in order to make a connect statement the first requirement is for the arguments to match, clicked() has no arguments while setText() has one, so there is a mismatch. As of how to resolve that mismatch, the easiest way is to use simple wrappers, although you can use a QSignalMapper and as of Qt5, lambdas and std::bind.
For starters, you cannot specify the actual argument instance in the connect statement, even with arguments on both sides you only need to specify the types to help resolve overloads (it is terrible with the new connection syntax in Qt5), and not any actual identifiers or literals.
In case of the more usual scenario, where the data is send to the slot by the caller, the identifier or literal is specified in the emit signal(value) statement. Since you don't have clicked(const QString &) you need a wrapper slot that you connect to clicked() and emit with the value in that wrapper slot, or subclass the button and add your own overload of clicked(QString).
In case the value is in the scope of the called, then subclassing doesn't make much sense, all you need is the wrapper slot in the scope of the called object.
If you want more, you will have to use Qt 5, whose syntax is significantly more powerful.
If the question is whats wrong, just remember the parameter number must be the same for the Signal and the Slot. Asking a collegue and according the Peppe, setText(QString) wait for One parameter and the Clicked() is empty...A custom slot is to call the setText() method indirectly.
You can look that : http://qt-project.org/doc/qt-4.8/widgets-calculator.html
It uses the QWidget, an important part of Qt interfaces beside QML.
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.