Re: Reload widget contents
Did you possibly forget Q_OBJECT in your DragWidget header file?
Re: Reload widget contents
Can you show the declaration for class DragWidget ?
Probably you didnt add slots: to draw() :rolleyes:
Re: Reload widget contents
@norobro
Well, apart from moving the label drawing code out of the constructor into the draw() slot, I haven't modified anything in the DragWidget class. In its original form, there's no Q_OBJECT macro in DragWidget declaration, and it compiles and runs as expected. But adding the macro to the DragWidget class, like this:
Code:
{
Q_OBJECT
public:
public slots:
void draw();
protected:
};
gave off this error:
collect2: ld returned 1 exit status
@aamer4yu
But I did, look at the class declaration, its there.
Re: Reload widget contents
Did you recompile ?
run qmake again
Re: Reload widget contents
I did recompile, the 'public slots:' declaration was there all the time, I didn't add it just now.
I ran qmake through Qt Creator, but the same error comes up. This is really weird, I've no idea what I'm doing wrong.
Re: Reload widget contents
here's the project if anyone's interested in checking out what's the problem
http://www.4shared.com/account/file/...gemagnets.html
Re: Reload widget contents
Okay, I don't know what manner of esoteric power was holding my computer back, but I added the Q_OBJECT macro to the DragWidget class and this time running qmake and running it again worked fine. Really weird.
My next step was storing the created labels in a QList and delete them before calling draw(). Seems to be working now. Here's the code to my modified DragWidget class:
Code:
{
Q_OBJECT
public:
public slots:
void draw();
void store();
void refreshWidget();
protected:
private:
QList<DragLabel*> labels;
};
and the implementation:
Code:
DragWidget
::DragWidget(QWidget *parent
){
store();
draw();
newPalette.
setColor(QPalette::Window, Qt
::white);
setPalette(newPalette);
setMinimumSize(400, 100);//qMax(200, y));
setWindowTitle(tr("Fridge Magnets"));
setAcceptDrops(true);
}
void DragWidget::draw(){
int x = 5;
int y = 5;
foreach(DragLabel* label, labels){
label->move(x,y);
label->show();
label->setAttribute(Qt::WA_DeleteOnClose);
x += label->width() + 2;
if (x >= 245) {
x = 5;
y += label->height() + 2;
}
}
}
void DragWidget::refreshWidget(){
store();
draw();
}
void DragWidget::store(){
foreach(DragLabel* label, labels){
label->deleteLater();
}
QFile dictionaryFile
("../words.txt");
dictionaryFile.
open(QFile::ReadOnly);
labels.clear();
while (!inputStream.atEnd()) {
inputStream >> word;
if (!word.isEmpty()) {
DragLabel *wordLabel = new DragLabel(word, this);
labels.append(wordLabel);
}
}
}
and the connect statement now calls refreshWidget() as a slot instead of draw(). It works fine now if you don't drag any labels before clicking the button. If i drag a label out of place and click the button, the program crashes. Any idea why that happens?
Re: Reload widget contents
Glad that you got it running. I was typing the following (slow typist) while you posted. I'll take a look at your next problem.
You have a stray comma in the wrapwidget.h that you uploaded:
Code:
#define WRAPWIDGET_H,
I removed the comma, uncommented Q_Object in dragwidget.h, reran qmake and it compiled.
Re: Reload widget contents
Here's the project, the button works but dragging a label before clicking the button crashes the program
http://www.4shared.com/file/23766778...magnets_2.html
I think it's because of the drop, but I'm not really sure what to do to fix this behaviour. I tried to append the new label created by the drop to the QList, but that didn't solve the problem.
Re: Reload widget contents
When you drag an item a new QLabel is created in DragWidget::dropEvent. That seems to invalidate your QList "labels" resulting in a segfault.
Try this:
Code:
void DragWidget::store(){
QList <QObject
*> newList
= this
->children
();
foreach
(QObject * label, newList
) label
->deleteLater
();
// foreach(DragLabel* label, labels){
// label->deleteLater();
// }
Re: Reload widget contents
It worked! I was so sure the error was on dropEvent()!
Could you elaborate more on why the segfault was happening? Also, you declared a QObject* list, could it have been a DragWidget* list instead?
How could I go about retrieving a particular set of objects instead of all the children?
Re: Reload widget contents
Sorry for the delay in responding. Right after my last post I lost my internet connection. Called my ISP and as usual their first reaction was to blame the customer's equipment, in this case my 7 year old modem. So I bought a new modem and they still couldn't get me connected. Had to send out a service tech and of course the problem was on their end.
Code:
{
. . .
if (drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::CopyAction) == Qt::MoveAction)
child->close();
. . .
When you move a "magnet" a new DragLabel is created and the above statement deletes the old one which leaves you with a dangling pointer in your list "labels". This results in a segfault when you iterate through the list because you are trying to delete a memory location that has already been deallocated. Try commenting out "child->close()" and use your foreach statement in DragWidget::store().
I tried using a DragLabel list first and got compile errors thus the QObject * list. You make a good point- you might not want to delete all of an object's children. I did find this in the docs so in this case the following should find all of the DragLabel children:
Code:
QList<DragLabel *> newList = this->findChildren<DragLabel *>();
Hope this makes sense.
Re: Reload widget contents
Sorry to hear you had trouble with your ISP, I'm all too familiar with your situation. Nice to have you back on the internets ;)
I see why the application was crashing now. Thanks a bunch for your help!