views:

34

answers:

1

I created a little widget on my own, including a QProgressBar and a QLabel in a QVBoxLayout. It has also a function which returns the text of the label (self-created). Now in my MainWindow I have two other QHBoxLayouts and I want to drag and drop my widget from one to another. It also works when I click on the little free space between the QLabel and the QProgressBar. But when I click on one of them directly, the application crashed and burned painfully.
I also know where it fails. My mousePressEvent looks like this:

void DragDrop::mousePressEvent(QMouseEvent *event) {

// !!!!---- make sure ONLY MyWidgets are here, else: CRASH ----!!!!
    MyWidget *child = static_cast<MyWidget*>(childAt(event->pos()));
    if (!child)
    return;

qDebug() << child->returnLabelText();
...

}

So when I click on the ProgressBar, it will cast the ProgressBar, not my own widget. And because the QProgressBar doesn't have a function like returnLabelText() (but my widget does) it fails.
What is a better method to get my widget?

+2  A: 

QWidget::childAt(int,int) returns the child widget, not the parent widget. In your case, it returns the QProgressBar. You then try to cast into a MyWidget, which it is not. What you are looking for is for the parent of the QProgressBar (or QLabel).

static_cast does not verify the type of the object you are trying to cast, and will always yield a non-null pointer even if the cast is invalid. What you are looking for here is dynamic_cast, which will return NULL if the object is not of the type you are looking for. Since you are looking for the parent (or an ancestor) of the widget being clicked, you could use a loop to iterate through the clicked widget's ancestry to find the instance of MyWidget you are looking for.

void DragDrop::mousePressEvent(QMouseEvent *event) {
  QWidget *widget = childAt(event->pos());
  do {
    MyWidget *myWidget = dynamic_cast<MyWidget*>(widget);
    widget = widget->parentWidget();
  } while (myWidget == NULL && widget != NULL)
  if (myWidget == NULL)
    return;

  qDebug() << myWidget->returnLabelText();
  // ...
}
Fred
qobject_cast would be better than dynamic_cast, just fyi..
ianmac45
ianmac45 is right... in the context of QObjects, qobject_cast is strongly prefered as it does not depend on RTTI.
Fred