From 10:00 CET Friday 22nd November we will adjust how the server works to deal with some recently reported problems. Therefore there may be a load problem, if you experience more problems than usual trying to access the forum then please PM AndyS or any of the moderators so they can inform me.


QThreads and Image loading from Ezust book



  • Hello, I am trying to implement an example that is on the Ezust book to acquire a bit of familiarity with QThreads. The book proposes to implement a sort of simple movie player dividing the problem in two classes: one for visualization and another for the model. The two main classes are as follows:

    #ifndef MOVIEVIEW_H
    #define MOVIEVIEW_H
    
    #include <QMainWindow>
    #include <QLabel>
    #include <QSlider>
    
    class MovieView : public QMainWindow
    {
        Q_OBJECT
    public:
        MovieView();
        ~MovieView();
    public slots:
        void setDelay(int newValue);
        void showPix(const QPixmap* pic);
    signals:
        void intervalChanged(int newValue);
    private:
        QLabel label;
        QSlider slider;
    };
    
    #endif // MOVIEVIEW_H
    

    Implementing

    #include "movieview.h"
    
    void MovieView::showPix(const QPixmap* pic) {
        label->setPixmap(*pic);
    }
    
    void MovieView::setDelay(int newValue) {
        QString str;
        str = QString("%1ms delay between frames").arg(newValue);
        slider->setToolTip(str);
        emit intervalChanged(newValue);
    }
    
    MovieView::MovieView() {
        resize(200, 200);
        slider = new QSlider(Qt::Vertical);
        slider->setRange(1,500);
        slider->setTickInterval(10);
        slider->setValue(100);
        slider->setToolTip("How fast is it spinning?");
        connect(slider, SIGNAL(valueChanged(int)), this,
                SLOT(setDelay(int)));
        QDockWidget *qdw = new QDockWidget("Delay");
        qdw->setWidget(slider);
        addDockWidget(Qt::LeftDockWidgetArea, qdw);
        label = new QLabel("Movie");
        setCentralWidget(label);
    }
    

    And the other class is

    #ifndef MOVIETHREAD_H
    #define MOVIETHREAD_H
    
    #include <QThread>
    #include <QVector>
    #include <QPixmap>
    #include <QString>
    
    class MovieThread
    {
        Q_OBJECT
    public:
        MovieThread();
        ~MovieThread();
        void run();
        void loadPics();
    public slots:
        void stop();
        void addFile(const QString& filename);
        void setInterval(int newDelay);
    signals:
        void show(const QPixmap*);
    private:
        QVector<QPixmap> m_Pics;
        int mDelay;
    };
    
    #endif // MOVIETHREAD_H
    

    implementing

    #include "moviethread.h"
    #include "filevisitor.h"
    
    
    MovieThread::MovieThread()
    {
        loadPics();
    }
    
    void MovieThread::run() {
        int current(0), picCount(m_Pics.size());
        while (true) {
            msleep(m_Delay);
            emit show(&m_Pics[current]);
            current = (current + 1) % picCount;
        }
    }
    
    void MovieThread::stop() {
    terminate();
    wait(5000);
    }
    
    void MovieThread::loadPics() {
        FileVisitor fv("*.png");
        connect (&fv, SIGNAL(foundFile(const QString&)),
                this, SLOT(addFile(const QString&)));
        fv.processEntry(":/images/");
    }
    
    void MovieThread::addFile(const QString& filename) {
        m_Pics << QPixmap(filename);
    }
    
    void MovieThread::setInterval(int newDelay)
    {
        m_Delay = newDelay;
    }
    

    Problem is I needed to implement an additional class in order to browse files

    #ifndef FILEVISITOR_H
    #define FILEVISITOR_H
    
    #include <QDir>
    #include <QObject>
    class FileVisitor : public QObject {
        Q_OBJECT
        public:
            FileVisitor(QString nameFilter="*",
                    bool recursive=true, bool symlinks=false);
        public slots:
            void processFileList(QStringList sl);
            void processEntry(QString pathname);
        signals:
            void foundFile(QString filename);
        protected:
            virtual void processFile(QString filename);
        protected:
            QString m_NameFilter;
            bool m_Recursive;
            QDir::Filters m_DirFilter;
    };
    
    #endif // FILEVISITOR_H
    
    
    void FileVisitor::processFile(QString filename) {
    // qDebug() << QString("FileVisitor::processFile(%1)").arg(filename);
        emit foundFile(filename);
    }
    
    void FileVisitor::processEntry(QString current) {
        QFileInfo finfo(current);
        processEntry(finfo);
    }
    
    void FileVisitor::processEntry(QFileInfo finfo) {
    // qDebug(QString("ProcessEntry: %1").arg(finfo.fileName()));
    if (finfo.isDir()) {
        QString dirname = finfo.fileName();
        if ((dirname==".") || (dirname == ".."))
            return;
        QDir d(finfo.filePath());
        if (skipDir(d))
            return;
        processDir(d);
    } else
        processFile(finfo.filePath());
    }
    
    void FileVisitor::processDir(QDir& d) {
        QStringList filters;
        filters += m_NameFilter;
        d.setSorting( QDir::Name );
        QStringList files = d.entryList(filters, m_DirFilter);
        foreach(QString entry, files) {
             processEntry(d.filePath(entry));
        }
        if (m_Recursive) {
            QStringList dirs = d.entryList(QDir::Dirs);
            foreach (QString dir, dirs) {
                processEntry(d.filePath(dir));
            }
        }
    }
    

    And the main is

    #include <QApplication>
    #include "moviethread.h"
    #include "movieview.h"
    
    int main(int argc, char** argv) {
        QApplication app(argc, argv);
        MovieView view;
        MovieThread movie;
        app.connect(&movie, SIGNAL(show(const QPixmap*)),
                    &view, SLOT(showPix(const QPixmap*)));
        app.connect(&view, SIGNAL(intervalChanged(int)),
                    &movie, SLOT(setInterval(int)));
        app.connect(&app, SIGNAL(aboutToQuit()), &movie, SLOT(stop()));
        movie.start();
        view.show();
        return app.exec();
    }
    

    I have added a resource file in the same folder where the project is and I have added the images in a folder (also located in the project folder) called "images".

    Since I am not very familiar with Threads (I am learning now) I can't get my head around some problems I bumped into: one for all is listed below. It pops up repeatedly for all the connects which are present in the main. Any idea?

    C:\Users\RXD308\QtProjects\Threads\main.cpp:10: error: no matching function for call to 'QApplication::connect(MovieThread*, const char*, MovieView*, const char*)'
                     &view, SLOT(showPix(const QPixmap*)));
                                                         ^