crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> ProgressBar на QtConcurrent
Fitz
  опции профиля:
сообщение 22.11.2010, 15:30
Сообщение #1


Студент
*

Группа: Новичок
Сообщений: 13
Регистрация: 22.11.2010
Пользователь №: 2207

Спасибо сказали: 0 раз(а)




Репутация:   0  


Уважаемые, хочу прикрутить к терминалу COM-порта ProgressBar загрузки файла в порт.
Сделав, соответстветственно, загрузку файла отдельным потоком.
Заюзал Qt'шный экзампл Progress Dialog, где используют QtConcurrent.

Код:
mainwindow.h
class MainWindow : public QMainWindow, public Ui::UARTxxx{
    Q_OBJECT
private:
    void loadFile(const QString &fileName);
public slots:
    void open();
}

mainwindow.cpp
void MainWindow::loadFile(const QString &fileName)
{
     QFile file(fileName);
     if (!file.open(QIODevice::ReadOnly))
       {
         QMessageBox::warning(this, tr("Application"),
                              tr("Cannot read file %1:\n%2.")
                              .arg(fileName)
                              .arg(file.errorString()));
         return;
       }

                // посылка QByteArray прочитанный из файла в порт

}

void MainWindow::open()
{
        QString fileName = QFileDialog::getOpenFileName(this);
        if (!fileName.isEmpty())
        {
            QProgressDialog dialog;
            QList<QString> fileList;
            fileList.append(fileName);
            dialog.setLabelText(QString("Downloading..."));

            QFutureWatcher<void> futureWatcher;
            connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset()));
            connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel()));
            connect(&futureWatcher, SIGNAL(progressRangeChanged(int, int)), &dialog, SLOT(setRange(int, int)));
            connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));

            futureWatcher.setFuture(QtConcurrent::map(fileList, MainWindow::loadFile));

            dialog.exec();

            futureWatcher.waitForFinished();
     }
}


Компилятор ругается в futureWatcher.setFuture(QtConcurrent::map(fileList, MainWindow::loadFile));, мол там нужен адрес функции, однако и подстановка адреса не помогает.
Что делаю не так?
Возможно есть более грамотное решение с QThread, подскажите.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 22.11.2010, 16:32
Сообщение #2


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


А ты посмотри в примерах, как определены функции для QtConcurrent::map. Являются ли они членами класса, как у тебя.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Fitz
  опции профиля:
сообщение 23.11.2010, 13:29
Сообщение #3


Студент
*

Группа: Новичок
Сообщений: 13
Регистрация: 22.11.2010
Пользователь №: 2207

Спасибо сказали: 0 раз(а)




Репутация:   0  


В примерах вообще класс не создается - просто некоторая (normal) функция и ее вызов через QtConcurrent в main().
Но насколько я понял из доки необходимо, чтобы функция void loadFile(const QString &fileName); была статической и принималась еще и по указателю.

Using Member Functions
Раскрывающийся текст

QtConcurrent::map(), QtConcurrent::mapped(), and QtConcurrent::mappedReduced() accept pointers to member functions. The member function class type must match the type stored in the sequence:

 // squeeze all strings in a QStringList
QStringList strings = ...;
QFuture<void> squeezedStrings = QtConcurrent::map(strings, &QString::squeeze);

// swap the rgb values of all pixels on a list of images
QList<QImage> images = ...;
QFuture<QImage> bgrImages = QtConcurrent::mapped(images, &QImage::rgbSwapped);

// create a set of the lengths of all strings in a list
QStringList strings = ...;
QFuture<QSet<int> > wordLengths = QtConcurrent::mappedReduced(string, &QString::length, &QSet<int>::insert);


Причем не важно членом какого класса она является.
Я прав?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 23.11.2010, 15:55
Сообщение #4


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Внимательно посмотри на приведенные примеры. Посмотри, что является входным параметром, с объектом какого класса происходит операция и с использованием какого метода.
Например, первый фрагмент:
Входные данные: strings - список строк;
Класс объекта для которого выполняется операция: QString - строка;
Какой метод применяется: QString::squeeze.

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Fitz
  опции профиля:
сообщение 24.11.2010, 20:14
Сообщение #5


Студент
*

Группа: Новичок
Сообщений: 13
Регистрация: 22.11.2010
Пользователь №: 2207

Спасибо сказали: 0 раз(а)




Репутация:   0  


После осознания наваял следующую конструкцию, котороая, как ни странно, заработала.

Создал отдельный класс прошивки:
ufirmware.h
class uFirmware
{
public:
    uFirmware(AbstractSerial *inPort, QString fileName);
    ~uFirmware();
    bool loadFile();

private:
    AbstractSerial *uPort;
    QString uFileName;
};

ufirmware.cpp
uFirmware::uFirmware(AbstractSerial *inPort, QString fileName)
{
    uPort = inPort;
    uFileName = fileName;
}

bool uFirmware::loadFile()
{
        QFile fFile(uFileName);
        QByteArray fileToArray = fFile.readAll();
      // бла-бла-бла

      uPort->write(fileToArray);
}

Теперь применение:
mainwindow.cpp
void MainWindow::open()
{
        QString fileName = QFileDialog::getOpenFileName(this);
        if (!fileName.isEmpty())
        {
QProgressDialog dialog;
            QList<uFirmware> fList;
            fList.append(uFirmware(port, fileName));
            dialog.setLabelText(QString("Downloading..."));

            QFutureWatcher<void> futureWatcher;
            connect(&futureWatcher, SIGNAL(finished()), &dialog, SLOT(reset()));
            connect(&dialog, SIGNAL(canceled()), &futureWatcher, SLOT(cancel()));
            connect(&futureWatcher, SIGNAL(progressRangeChanged(int, int)), &dialog, SLOT(setRange(int, int)));
            connect(&futureWatcher, SIGNAL(progressValueChanged(int)), &dialog, SLOT(setValue(int)));

            futureWatcher.setFuture(QtConcurrent::map(fList, &uFirmware::loadFile));

            dialog.exec();

            futureWatcher.waitForFinished();
     }
}


Вопрос раз: необходимо ли делать класс uFirmware потокобезопасным?
Вопрос два: код работает не совсем так, как мечталось - futureWatcher вычисляет только работу метода класса, а вот используемый им метод сторонней библиотеки AbstractSerial::write(QByteArray a)(в интересах которого, собственно, и выделяется отдельный поток) в расчет не берется.
Выходит надо работать напрямую с классом AbstractSerial? Но тогда каким образом передавать методу записи в порт write(QByteArray a) этот внешний параметр?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 19.4.2024, 20:01