Как обрабатывать прогрессбар в QT / C ++, когда значение обновления используется в качестве обратного вызова

Я пишу приложение для передачи файлов между устройством Android и Mac. Tha Передача файлов работает, но с точки зрения пользовательского опыта я хотел бы добавить индикатор выполнения, чтобы можно было видеть, когда передача завершена.

Поскольку я перехожу на устройство Android, мне пришлось использовать стек MTP. Функция, используемая для копирования файла

LIBMTP_Send_File_From_File(device, path, genfile, ProgressBar, NULL);

ProgressBar — это функция обратного вызова, а стек MTP написан на C.

Мое приложение написано на C ++ / Qt.

Сначала я спроектировал индикатор выполнения и ожидал использования механизма CONNECT / SIGNAL / SLOT для обновления индикатора выполнения, но он не работает.

Что я сделал, так это в dialog.h определил мой обратный вызов:

extern "C" int ProgressBar(const uint64_t data_sent, const uint64_t data_total, void const * const data);

и класс для разработки диалогового окна.

class Dialog : public QWidget
{
Q_OBJECT
public:
Dialog();
void CreateProgressBar();
void DestroyProgressBar();

private:
QWidget *ProgressDialog;
QProgressBar *ProgressIndicator;
QVBoxLayout *ProgressLayout;

QPushButton *CancelButton;

private slots:
void onCancelButtonAction();
};

В Dialog.c,

Dialog::Dialog()
{
}

void Dialog::CreateProgressBar() {
ProgressDialog = new QWidget(this);
ProgressDialog->setWindowTitle("Progress");

ProgressLayout = new QVBoxLayout(this);

ProgressIndicator = new QProgressBar();
ProgressIndicator->resize(200,25);
//ProgressIndicator->setrange(0,100);
ProgressIndicator->setValue(0);
ProgressIndicator->setOrientation(Qt::Horizontal);
connect(ProgressIndicator,SIGNAL(ProgressBar(const uint64_t, const uint64_t, void const * const)),ProgressIndicator,SLOT(setValue(int)));

CancelButton = new QPushButton();
CancelButton->setFixedSize(25,25);
CancelButton->setText("Cancel");
CancelButton->setFlat(true);
CancelButton->setAutoFillBackground(true);
CancelButton->setStyleSheet("QPushButton { background-color : white;}");
connect(CancelButton, SIGNAL(clicked()), this, SLOT(onCancelButtonAction()));

ProgressLayout->addWidget(ProgressIndicator);
ProgressLayout->addWidget(CancelButton);

ProgressDialog->setLayout(ProgressLayout);
ProgressDialog->show();
}

void Dialog::DestroyProgressBar() {
ProgressDialog->close();
}

void Dialog::onCancelButtonAction() {
DestroyProgressBar();
}

и код C для «ProgressBar»

int ProgressBar(const uint64_t data_sent, const uint64_t data_total, void const * const data) {
return (data_sent * 100) / data_total;
}

Это в основном не работает, потому что connect отклоняет соединение SIGNAL с ProgressBar, потому что он не является частью класса.

С другой стороны, если я перемещу ProgressBar в моем классе, соединение в порядке, но код не создается, потому что LIBMTP_Send отклоняет использование класса.

Я вызываю ProgressBar в LIBMTP_Send … используя MyProgress.ProgressBar

    Dialog MyProgress;
MyProgress.CreateProgressBar();

LIBMTP_Send_File_From_File(device, path, genfile, MyProgress.ProgressBar, NULL);

Это не работает, потому что я использую вызов метода, если мой класс вместо C обратного вызова

Мой метод при попытке использовать класс вместо кода C определяется следующим образом:

int Dialog::ProgressBar(const uint64_t data_sent, const uint64_t data_total, void const * const data) {
char* tmp_string;
char* tmp_sent;
char* tmp_total;

if(ProgressIndicator.destroyed() == true)
return true;

if (ProgressIndicator != NULL) {

ProgressIndicator->setValue();
}

if (progressDialog != NULL) {
return (data_sent * 100) / data_total;
}
return 0;
}

В этом случае я делаю:

ret = LIBMTP_Send_File_From_File(PulsDeviceMngr->device, strdup(AbsolutePath), genfile, MyProgress.ProgressBar, NULL);

но ошибка сборки такова: должна быть вызвана ссылка на нестатическую функцию-член

Я создаю экземпляр Dialog в коде, который вызвал функцию LIBMTP, как показано ниже:

  Dialog MyProgress;
MyProgress.CreateProgressBar();

genfile = LIBMTP_new_file_t();
...

ret = LIBMTP_Send_File_From_File(PulsDeviceMngr->device, strdup(AbsolutePath), genfile, MyProgress.ProgressBar, NULL);

Я действительно застрял … пусто 🙂

0

Решение

Для этого вам нужно будет передать указатель на класс в качестве аргумента обратного вызова в

LIBMTP_Send_File_From_File(device, path, genfile, MyProgress.ProgressBar, NULL);

NULL Аргумент является аргументом обратного вызова

Dialog *MyProgress = new Dialog(parentWindow);
LIBMTP_Send_File_From_File(device, path, genfile, ProgressBar, MyProgress);
/* ^ here a pointer to */
/*   progress dialog   */

Заметка: parentWindow может быть вашим QMainWindow и это очень важно, иначе у вас будет утечка памяти.

тогда в обратном вызове аргумент данных будет указывать на диалог, так что вы можете сделать

Dialog *dialog = reinterpret_cast<Dialog *>(data);
dialog->setValue((data_sent * 100) / data_total);
1

Другие решения


По вопросам рекламы [email protected]