Difficulty Understanding The Draggable Icons Example
-
Hello, I am new with C++ and QT, but making steady progress.
Quick background: I have created an application that uses a QGridLayout as the central widget on the mainwindow, and has a QDockWidget. The idea being that I can drag icons from the QDockWidget over to the QGridLayout. I started with the "Draggable Icons Example" to get this far, and I have it working pretty well.
Straight from the example, I have a DragWidget that uses QFrame as a base class. Though I don't want multiple icons per DragWidget, so I stripped out all the QLabels from the example, except one.
So far so good.
Now I want icons that have independant behavior so I created a "virtual" function inside of DragWidget and then subclass DragWidget with multiple classes: AlphaWidget, BetaWidget, and so on. Doing this, the drag and drop functionality still works great.
Here is the function as defined in dragwidget.h:
@protected:
virtual void createChildren(int row, int column);
@And here are a couple of functions in dragwidget.cpp:
@void DragWidget::createChildren(int row, int column) {
QMessageBox::information(NULL, "createChildren", "Base");
}void DragWidget::mouseDoubleClickEvent(QMouseEvent * event) {
QMessageBox::information(NULL, "mouseDoubleClickEvent", this->metaObject()->className());
createChildren(1,1);
event->ignore();
}
@And in alphawidget.h I have:
@protected:
virtual void createChildren(int row, int column);
@And the alphawidget.cpp:
@void AlphaWidget::createChildren(int row, int column) {
QMessageBox::information(NULL, "createChildren", "subclass");
}
@The first problem: When I double click the icon in the DockWidget, I had an expectation this->metaObject()->className() should say "AlphaWidget". But it always says "QFrame", regardless whether the icon is a DragWidget or AlphaWidget. So I am misunderstanding something fundamental and can't get my brain around it. Why doesn't it say "AlphaWidget" or "DragWidget", depending on which class the icon actually is?
The second problem: When I call createChildren in the mouseDoubleClickEvent() function, things work well and I get "base" when I click on a DragWidget, but "subclass" when I click on an AlphaWidget. However, after dragging the icon to the GridLayout, when I double click on it, it always calls the DragWidget version of the virtual function so it always says "base" regardless whether it was originally a DragWidget or AlphaWidget. In other words the DragWidget::dropEvent(...) method appears to be making a DragWidget when it copies the icon. So how might I get it to copy an AlphaWidget?
Thanks in advance.
-
Well, for the first question about className(), I think unless you register that class type with Qt it won't know what it is. So it won't say AlphaWidget when using QMetaObject unless you have registered it previously.
For registering look into qRegisterMetaType. I rarely use this unless I need to pass custom types through signal/slot mechanism though. Not sure why you need className but if you do you will have to register it.
For the next problem, I would need to see the full class definition (header files) and your instantiation code for them. It sounds like a C++ polymorphism problem. You are expecting the derived class to be called by the base class is called instead. I will need to at least see where the objects are created, and possibly the reimplemented functions common to base and derived classes.
-
[quote author="ambershark" date="1405553990"]Well, for the first question about className(), I think unless you register that class type with Qt it won't know what it is. So it won't say AlphaWidget when using QMetaObject unless you have registered it previously.
For registering look into qRegisterMetaType. I rarely use this unless I need to pass custom types through signal/slot mechanism though. Not sure why you need className but if you do you will have to register it.[/quote]
Ahhhh. That makes sense now. I don't need the className, I was just trying to use it troubleshoot the second problem. I couldn't figure out if I was actually dealing with an AlphaWidget, DragWidget or QFrame.
[quote author="ambershark" date="1405553990"]For the next problem, I would need to see the full class definition (header files) and your instantiation code for them. It sounds like a C++ polymorphism problem. You are expecting the derived class to be called by the base class is called instead. I will need to at least see where the objects are created, and possibly the reimplemented functions common to base and derived classes.[/quote]
I believe I just figured this out. I didn't fully appreciate that the DragWidget::dropEvent() example function isn't really creating a new copy of the source object. It's simply using the target object that already exists and either copying the data over to it and then deleting the original data (in the case of a move), or copying and leaving the original data in tact (in the case of a copy).
The source can be an AlphaWidget, BetaWidget, etc (from the DockWidget), but the GridLayout is populated with a bunch of "blank" DragWidget targets, so the target will always be a DragWidget.
So I believe the solution for me will be to somehow use the MimeData to pass the class type and dynamically instantiate a new object of the proper type and swap the target DragWidget with a new AlphaWidget (or whatever the source is).
-
That makes sense on why you were having trouble. Now that you figured out the problem you should be able to solve it. Mime information would work to tell you what type of data and therefore what class it should be put into.
-
Hi,
The class doesn't need to be registered to use className(). It all depends on which metaObject you are getting, if it's the one from the derived class or the one from the base class
-
Could someone give me a hint as to what I should be reading up on to dynamically instantiate an object, given only a class name as a string. I guess this would be analogous to Java's reflection, but have no idea how to do this in C++ or QT -- I don't even know what to Google to get started.
Edit: Oops, I just found this thread: http://www.qtcentre.org/threads/42006-Reflection-on-Qt
If there is a newer or better way to go about this let me know, meanwhile I will begin using that thread as a guide.
Edit edit: Nevermind. I don't need reflection. I just need a case statement that creates a well known object based on a type being passed. Sheesh.