Many nested QFrame widgets render somewhat slow
-
I'm writing some code which will display a threaded conversation. There are many nested QFrames, each reply is a child of the previous post's QFrame. This is as a mockup of what I am doing !http://i.imgur.com/1NIFEqZ.png()!
The code to generate the widgets is fast, I watch in the console/qDebug output for when the recursion into the conversation begins and when it stops and that part is fast, but then it takes a few seconds for the QFrames and other controls to render/show up. There are about 200 posts in the discussion thread I'm testing.
The slowness is fairly tolerable, but, I am duplicating something which is already done on the web, and the same thing renders faster there! The point of Qt was to have a fast local app. hehe But to reiterate, the code which generates the QFrames is fast. but there is a delay from when that code finishes until the controls actually show up.
Is there anything I can do do speed this up? Would using the tree view with a custom delegate be better? (The only reason I didn't is because I don't know how).
Thank You!
-
200 widgets should be still rather fast if you don't do any unnecessary stuff.
Please show some code of the creation and layouting of the widgets.Note when running in debug mode the application is slower than in release mode. Many debug prints might also slow down the application.
-
In basic the QTreeView/Model works roughly the same as a QTreeWidget, but totally different from a QFrame (nested). Still, like raven-worx says, it should remain pretty fast even when multiple frames are displayed. What OS do you use and which Qt version?
Then try in release mode, the debugger will slow things down!
greetz -
Okay, slightly embarrassed to post this code. 1. I'm a newb, 2. it is a work in progress. I bet there are things that could be done more nicely, but, just looking to solve the speed problem. Here is an animated gif of what is happening !http://bigimagehost.net/images/2013/12/06/output.gif()! It should be noted that there will be more controls than there are now. So the problem will get worse. In creating this demo, I noticed the amount of text has a pretty big difference on loading speed. I'm on a modern i7 system, Ubuntu 13.10 and qt 5.2 compiled by me.
The first thing I tried was release mode, unfortunately no luck.
@void MainWindow::drawComments()
{
RSubmissionPost * sp = new RSubmissionPost();
sp->loadTestCommentJson();
QList<RComment *> comments = sp->getComments();qDebug() << "drawing started"; for (int x=0; x < comments.size();x++) { QVBoxLayout * commentLayout = new QVBoxLayout; this->drawComment2(comments.at(x), commentLayout); QWidget * spacerWidget = new QWidget(); QLabel * spacer = new QLabel(); spacer->setText("----------------------------------------"); spacer->setParent(spacerWidget); spacer->setMinimumHeight(10); spacer->setAlignment(Qt::AlignVCenter); spacerWidget->setMinimumHeight(10); commentLayout->addWidget(spacerWidget); ui->commentsVerticalLayout->addLayout(commentLayout); } connect(commentReplySignalMapper, SIGNAL(mapped(const int &)), this, SLOT(commentReplyClicked(int))); qDebug() << "drawing done";
}
void MainWindow::drawComment2(RComment * comment, QVBoxLayout * parentLayout)
{
QFrame * qf = new QFrame();
qf->setFrameStyle(2);
qf->setMaximumWidth(700);
QVBoxLayout * vl = new QVBoxLayout();this->drawComment(vl, qf, comment); qf->setLayout(vl); for (int i=0; i < comment->getReplies().size(); i++) { this->drawComment2(comment->getReplies().at(i), vl); } parentLayout->addWidget(qf);
}
void MainWindow::drawComment(QVBoxLayout * parentLayout, QFrame * parentFrame, RComment * comment)
{
QHBoxLayout * outerLayout = new QHBoxLayout();
QVBoxLayout * leftCol = new QVBoxLayout();
QPushButton * b1 = new QPushButton();
b1->setText("b1");
b1->setMaximumWidth(15);
QPushButton * b2 = new QPushButton();
b2->setText("b2");
b2->setMaximumWidth(15);leftCol->addWidget(b1); leftCol->addWidget(b2); QVBoxLayout * rightCol = new QVBoxLayout(); int vLayoutIndex = this->vLayouts.size(); // must be before next line this->vLayouts.append(rightCol); QHBoxLayout * rightTop = new QHBoxLayout(); QPushButton * collapse = new QPushButton(); collapse->setText("[-]"); collapse->setMaximumWidth(15); QPushButton * userName = new QPushButton(); userName->setText("coolJoe"); //TODO userName->setMaximumWidth(70); rightTop->addWidget(collapse); rightTop->addWidget(userName); QLabel * commentLabel = new QLabel(); commentLabel->setWordWrap(true); commentLabel->setTextFormat(Qt::RichText); commentLabel->setMinimumWidth(700); //commentLabel->setParent(parent); commentLabel->setAlignment(Qt::AlignVCenter); QString txt = comment->getBody(); txt = this->htmlDecode(txt); commentLabel->setText(txt); commentLabel->adjustSize(); commentLabel->setMinimumHeight(22); QPushButton * replyButton = new QPushButton(); replyButton->setText("reply"); replyButton->setMaximumWidth(40); connect(replyButton, SIGNAL(clicked()), commentReplySignalMapper, SLOT(map())); commentReplySignalMapper->setMapping(replyButton, vLayoutIndex); rightCol->addLayout(rightTop); rightCol->addWidget(commentLabel); rightCol->addWidget(replyButton); outerLayout->addLayout(leftCol); outerLayout->addLayout(rightCol); // this calculation isn't even right now that there is more than just a // single label, all the item heights should need to be accounted for // but they aren't, and it's working :/ // as of posting on qt-project I realized I have done something that makes this not required //parentFrame->setMinimumHeight(parentFrame->minimumHeight()+commentLabel->height()); outerLayout->addWidget(commentLabel); parentLayout->addLayout(outerLayout);
QString MainWindow::htmlDecode(QString str)
{
// this would need to account for items being escaped no?
// if so, I think it does, this doesn't not work properly
QList< QList < QString > > replacements;
QList<QString> x;// when posting to qt-project I noticed in the preview that the encoded html might be interperted
x.append("<");
x.append("<");replacements.append(x); x.clear(); x.append(">"); x.append(">"); replacements.append(x); x.clear(); x.append("&"); x.append("&"); replacements.append(x); x.clear(); for (int i=0; i < replacements.size(); i++) { QList <QString> current = replacements.at(i); str.replace(current.at(1), current.at(0)); } return str;
}
}void MainWindow::commentReplyClicked(int vLayoutIndex)
{
qDebug() << "Reply Clicked";
QVBoxLayout * vLayout = this->vLayouts.at(vLayoutIndex);
QPushButton * test = new QPushButton("ffff");
vLayout->addWidget(test);
}@