PDA

View Full Version : how to iterate over images and display them in sets of 8 (on QPushbuttons)



rishiraj
7th May 2009, 10:54
Hi everyone,
I have a picture gallery application in which there are 8 QPushbuttons on top of which the pixmaps are set.On clicking the buttons(once the pixmaps are set on them),one can view them in enlarged form and do the usual things like rotate,zoomin/out etc.
My problem is that I have got more than 8 images in the picture folder so,I want to iterate over the images and display them in batches of 8...meaning,first time,it shows the first 8 images then after a couple of secs it shows the next 8 and so on till all the pics have been shown and then it again starts from the first 8 and goes on(till the user clicks on any of the pics to enlarge it).
I tried the following code:-


void Photogallery::createbuttons() //function called from constructor to create the
//8 pushbuttons
{
<<<<code to create the 8 buttons>>>
QDir CurrentDirectory("/root/Desktop/photos"); //'photos' dir. contains pictures
names= CurrentDirectory.entryList(QDir::Files|QDir::NoDot AndDotDot);
//'names' is a Qstringlist variable
timer=new QTimer(this);
connect(timer,SIGNAL(timeout()),this,SLOT(update() ));
timer->start();
}

void Mediagallery::update() //slot which sets up the images on buttons
{

it= names.begin(); //'it' is QStringlist iterator
int count=(names.size()/8);

for(int numimage=0;numimage<count;numimage++)
{
//first picture on first button.
QString Imagename(*it5);
firstImagepath = "/root/Desktop/photos/"+Imagename;
QPixmap imagedisplay(firstImagepath);
QIcon icon(imagedisplay);
firstImage->setIcon(icon); //firstImage is a Qpushbutton
connect(firstImage,SIGNAL(pressed()),this,SLOT(but tondown()));
//buttondown() is a slot where I identify which button is clicked.
//************************************************** *********
//second picture on second button
it5++;
QString Imagename2(*it5);
secondImagepath = "/root/Desktop/photos/"+Imagename2;
QPixmap imagedisplay2(secondImagepath);
secondImage->setIcon(imagedisplay2);
connect(secondImage,SIGNAL(pressed()),this,SLOT(bu ttondown()));
//************************************************** ***********
//third picture on third pushbutton
it5++;
QString Imagename3(*it5);
thirdImagepath= "/root/Desktop/photos/"+Imagename3;
QPixmap imagedisplay3(thirdImagepath);
thirdImage->setIcon(imagedisplay3);
connect(thirdImage,SIGNAL(pressed()),this,SLOT(but tondown()));

.........so on till 8th image is set.

QString numimagestr=QString::number(numimage);
QMessageBox::information(NULL,"",numimagestr); //keeping count
}
}


If I remove the 'QMessageBox' statement towards the end of the loop,all I get are eight empty pushbuttons (No pictures are set on them).If I keep the QMessageBox,I get the images in batches on the buttons(as expected) but,I cannot click on any of the pictures to enlarge it as the MessageBox keeps coming in the foreground.
I want the pics to show in batches of 8 without the presence of the MessageBox.
Any ideas on how to do that(maybe I need to change the logic) or use a Timer or something else at some point ....Need your advice on how to proceed.
Thank you.

wysota
7th May 2009, 11:11
What is the base class of your Mediagallery class?

rishiraj
7th May 2009, 11:14
QMainWindow()

wysota
7th May 2009, 11:28
In that case you have to change the name of the slot from update() to something else. There already exists such a slot and it does something important so better rename yours to something else.

And setup the connections between signals and slots once instead of doing it each time you update the images.

rishiraj
7th May 2009, 11:52
Thank you,there's some improvement now.
Changed 'update()' to 'updatepics()' and moved the signals-slots to the constructor.
Now,If I don't use the 'QMessageBox',the last eight images in the folder are displayed on the QPushButtons and I can click on them and enlarge them(as is the plan).
But,the other images(before the last eight) are not shown...how can I modify the code so that it shows all the images from first to last in batches of 8 and not just the last 8 images...something like display the first 8 images then wait for 5 seconds,show the second set and so on......any ideas/suggestions are welcome.
Thank you.

wysota
7th May 2009, 12:37
The "for" loop you have iterates over all images thus you see the last eight. You should have a single iteration modifying eight images starting from the one after the last displayed one.


#include <QtGui>

class Gallery : public QWidget {
public:
Gallery(const QString &dirName) {
QGridLayout *l = new QGridLayout(this);
for(int i=0;i<9;i++){
QLabel *lab = new QLabel;
l->addWidget(lab, i / 3, i % 3);
lab->setFixedSize(200,200);
lab->setAlignment(Qt::AlignCenter);
labels << lab;
}
imagePaths = QDir(dirName).entryList(QStringList() << "*.jpg" << "*.png" << "*.bmp");
m_dirName = dirName;
m_nextImage = 0;
}
void start(int ms){
m_timer = startTimer(ms);
m_nextImage = 0;
updateLabels();
}
void stop(){
killTimer(m_timer);
}
protected:
void timerEvent(QTimerEvent *tev){
updateLabels();
}
void updateLabels(){
for(int i=0;i<9;i++){
if(m_nextImage>=imagePaths.size()){
labels[i]->setPixmap(QPixmap());
} else {
labels[i]->setPixmap(QPixmap(m_dirName+QDir::separator()+imag ePaths.at(m_nextImage)).scaled(QSize(200,200), Qt::KeepAspectRatio, Qt::SmoothTransformation));
}
m_nextImage++;
}
if(m_nextImage>=imagePaths.size()) m_nextImage = 0;
}
private:
QList<QLabel*> labels;
int m_timer;
int m_nextImage;
QString m_dirName;
QStringList imagePaths;
};

int main(int argc, char **argv){
QApplication app(argc, argv);
Gallery gal(argv[1]);
gal.show();
gal.start(5000);
return app.exec();
}

rishiraj
8th May 2009, 07:47
Hi,
Thanks Wysota.
I modified the code as you suggested and, it's working properly for now.Will need to make a couple of changes to make it perfect...but,it's doing what I wanted it to do,that's iterate over the images and display them on the pushbuttons.


void Mediagallery::updatepics()
{
timer->stop();
int numimage=0;
int count=(names.size()/8);
if(counter<count) //counter has initial value '0'.
{
if(numimage<=8)
{
QString Imagename(*it5);
NextImagepath = "/root/Desktop/photos/"+Imagename;
QPixmap imagedisplay(NextImagepath);

QIcon icon(imagedisplay);

mainImage->setIcon(icon);
numimage++;




it5++;

QString Imagename2(*it5);

NextImagepath2 = "/root/Desktop/photos/"+Imagename2;
QPixmap imagedisplay2(NextImagepath2);

bottmImage->setIcon(imagedisplay2);
numimage++;



it5++;

QString Imagename3(*it5);

NextImagepath3 = "/root/Desktop/photos/"+Imagename3;
QPixmap imagedisplay3(NextImagepath3);

leftImage1->setIcon(imagedisplay3);
numimage++;



it5++;

QString Imagename4(*it5);

NextImagepath4 = "/root/Desktop/photos/"+Imagename4;
QPixmap imagedisplay4(NextImagepath4);

leftImage2->setIcon(imagedisplay4);
numimage++;



it5++;

QString Imagename5(*it5);

NextImagepath5 = "/root/Desktop/photos/"+Imagename5;
QPixmap imagedisplay5(NextImagepath5);

leftImage3->setIcon(imagedisplay5);
numimage++;



it5++;

QString Imagename6(*it5);

NextImagepath6 = "/root/Desktop/photos/"+Imagename6;
QPixmap imagedisplay6(NextImagepath6);

rightImage1->setIcon(imagedisplay6);
numimage++;



it5++;

QString Imagename7(*it5);

NextImagepath7 = "/root/Desktop/photos/"+Imagename7;
QPixmap imagedisplay7(NextImagepath7);

rightImage2->setIcon(imagedisplay7);
numimage++;



it5++;

QString Imagename8(*it5);

NextImagepath8 = "/root/Desktop/photos/"+Imagename8;
QPixmap imagedisplay8(NextImagepath8);

rightImage3->setIcon(imagedisplay8);
numimage++;

it5++;

counter++;
timer1=new QTimer(this);
connect(timer1,SIGNAL(timeout()),this,SLOT(updatep ics()));
timer1->start(7000);

}
}
else
{
timer1->stop();
}
}

wysota
8th May 2009, 07:57
Don't you start a new timer at each call to updatepics()? After some time you will have lots of timers while you only need one.

rishiraj
8th May 2009, 09:14
true...no wonder I am getting segmentation faults.The first batch of 8 images and the last set of 8 images can be enlarged by clicking on them...but in the other batches,after I enlarge them,I get segmentation faults....I didn't check that out till now,so,will try to correct it.Thanks once again.