Просмотр сообщений
|
Страниц: [1] 2 3 ... 32
|
1
|
Qt / Многопоточное программирование, процессы / Re: Программно нарисовать тень в QImage
|
: Сентябрь 02, 2020, 15:06
|
Добрый день! Подскажите, как можно программно нарисовать тень на картинках в отдельных потоках? Есть 10к изображений, которые нужно обработать. Сейчас использую QThread + QGraphicsDropShadowEffect, но QGraphicsScene, которая нужна для отрисовки тени через QGraphicsDropShadowEffect - не thread-safety, поэтому иногда крашит приложение. Может быть есть еще какие-нибудь варианты?
Если не хочется изобретать велосипед, то идёшь в исходники, и берёшь от туда код, отвечающий за отбрасывание тени: C++ (Qt) void QPixmapDropShadowFilter::draw(QPainter *p, const QPointF &pos, const QPixmap &px, const QRectF &src) const { Q_D(const QPixmapDropShadowFilter); if (px.isNull()) return; QImage tmp(px.size(), QImage::Format_ARGB32_Premultiplied); tmp.setDevicePixelRatio(px.devicePixelRatioF()); tmp.fill(0); QPainter tmpPainter(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_Source); tmpPainter.drawPixmap(d->offset, px); tmpPainter.end(); // blur the alpha channel QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied); blurred.setDevicePixelRatio(px.devicePixelRatioF()); blurred.fill(0); QPainter blurPainter(&blurred); qt_blurImage(&blurPainter, tmp, d->radius, false, true); blurPainter.end(); tmp = blurred; // blacken the image... tmpPainter.begin(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); tmpPainter.fillRect(tmp.rect(), d->color); tmpPainter.end(); // draw the blurred drop shadow... p->drawImage(pos, tmp); // Draw the actual pixmap... p->drawPixmap(pos, px, src); }
Вместо QPixmap используешь QImage, ибо QPixmap умеет только в GUI потоке работать.
|
|
|
3
|
Qt / Общие вопросы / Re: QProcess и консольное приложение
|
: Апрель 22, 2018, 09:17
|
C++ (Qt) #include <QMainWindow> #include <QApplication> #include <QProcess> #include <qDebug> // https://sourceforge.net/projects/sox/ - ссылка где скачал Sox - Sound eXchange int main(int argc, char *argv[]) { QApplication a(argc, argv); QMainWindow w; QProcess process; QStringList strList; process.start("D://FolderSox//sox-14-4-2//sox", strList); process.waitForReadyRead(-1); QString strWrite = "track01.wav track02.wav Sometrack03.wav"; process.write(strWrite.toLatin1()); process.waitForBytesWritten(); process.waitForReadyRead(); qDebug() << "Text " << process.readAll() <<endl; // QProcess process; // Так тоже не работает // QStringList strList; // strList << "track01.wav"; // strList << "track02.wav"; // strList << "Sometrack03.wav"; // process.start("D://FolderSox//sox-14-4-2//sox.exe", strList); // qDebug() << "Text2 " << process.exitCode() <<endl; w.show(); return a.exec(); }
Помогите пожалуйста. Через консоль пробовал все работает. А где твои wav файлы находятся? Попробуй указать полные пути до них.
|
|
|
4
|
Qt / Общие вопросы / Re: QProcess и консольное приложение
|
: Март 22, 2018, 14:28
|
Может кто-то помочь? Почему не работает? Консольная программа (sox) должна объединить два трека, через cmd вручную проверял - работает, однако написанный код не работает. C++ (Qt) void MainWindow::on_pushButton_begin_clicked() { QProcess process; QStringList strListKey; strListKey << "track01.wav track02.wav result.wav"; process.start(QDir::currentPath() + "/SoX-Sound_eXchange/sox.exe", strListKey); process.waitForFinished(-1); }
Мне кажется дело может быть в этом: C++ (Qt) strListKey << "track01.wav track02.wav result.wav";
надо так: C++ (Qt) strListKey << "track01.wav" << "track02.wav" << "result.wav";
|
|
|
7
|
Qt / Qt-инструментарий / Re: Как убрать теневую сборку?
|
: Декабрь 29, 2017, 11:54
|
мне она мешает. смысла, для себя, в ней не вижу.
интересно, а какой смысл замусоривания сборочными данными исходный код в одном каталоге ? А зачем мусорить объектными файлами в каталоге с исходниками? Добавляем в pro файл следующие строки, отключаем теневую сборку и радуемся: CONFIG(debug, debug|release):{OBJECTS_DIR = $$PWD/../build/appname/debug/obj} else:{OBJECTS_DIR = $$PWD/../build/appname/release/obj} RCC_DIR = $$PWD/../build/appname/rcc UI_DIR = $$PWD/../build/appname/ui MOC_DIR = $$PWD/../build/appname/moc DESTDIR = $$PWD/../app
|
|
|
9
|
Qt / Многопоточное программирование, процессы / Re: Как завершить поток таймера?
|
: Декабрь 12, 2017, 17:36
|
последующий вызов QThread::wait() гарантирует как минимум еще одну итерацию event loop потока
wait ничего не гарантирует, даже более он сам блокирует поток в котором запущен до завершения ожидаемой нитки. В это время eventloop не крутиться. то есть связка последовательных вызовов QThread::quit + QThread::wait не гарантирует итерации eventLoop'а? Как тогда корректно завершить поток с удалением всех его children'ов?
|
|
|
10
|
Qt / Многопоточное программирование, процессы / Re: Как завершить поток таймера?
|
: Декабрь 12, 2017, 17:02
|
Здесь смущает только место использования C++ (Qt) mWorker->deleteLater();
Если поток уже завершен, то event loop уже остановлена и некому выполнять deleteLater). А так, использование Worker в разных вариациях предпочтительнее. Наследование от потока тоже корректно, здесь на вкус и цвет, кому как удобнее. Поток останавливается ниже в деструкторе. Вызов QThread::quit и последующий вызов QThread::wait() гарантирует как минимум еще одну итерацию event loop потока, которая в свою очередь обеспечит удаление все запланированных к удалению объектов, привязанных к данному потоку.
|
|
|
11
|
Qt / Многопоточное программирование, процессы / Re: Как завершить поток таймера?
|
: Декабрь 12, 2017, 16:20
|
По мне дык наследование от QThread и переопределение в нем метода run() не очень хорошая практика. Использую механизм "воркеров", как то всё прозрачней получается, и проще следить за временем жизни объектов. Вот синтетический пример: C++ (Qt) #include <QCoreApplication> #include <QThread> #include <QTimer> #include <QDebug> class Worker : public QObject { Q_OBJECT public: Worker(QObject *parent = 0) : QObject(parent), mTimer(0) {} ~Worker() { qDebug() << Q_FUNC_INFO; } Q_INVOKABLE void start() { // для того, что бы создать таймер в контексте потока, в который перемещён // воркер, используем QMetaObject::invokeMethod if (QThread::currentThread() != thread()) { QMetaObject::invokeMethod(this, "start", Qt::QueuedConnection); return; } mTimer = new QTimer(this); connect(mTimer, &QTimer::timeout, this, &Worker::onTimeout); mTimer->start(1000); } signals: void timeout(); private: void onTimeout() { qDebug() << "worker" << QThread::currentThreadId(); emit timeout(); } private: QTimer *mTimer; }; class Test : public QObject { Q_OBJECT public: Test(QObject *parent = 0) : QObject(parent), mWorker(new Worker()) { connect(mWorker, &Worker::timeout, this, &Test::onTimeout, Qt::QueuedConnection); } ~Test() { // планируем удаление воркера mWorker->deleteLater(); if (mThread.isRunning()) { // рубим поток mThread.quit(); // даём время уничтожится воркеру mThread.wait(); } qDebug() << Q_FUNC_INFO; } void start() { // перемещаем воркер в отдельный поток mWorker->moveToThread(&mThread); // стратуем поток mThread.start(); // и воркер mWorker->start(); // планируем через 5 секунд выход из тестового приложения QTimer::singleShot(5000, this, &Test::onQuitTimeout); } void onTimeout() { qDebug() << "test" << QThread::currentThreadId(); } void onQuitTimeout() { qApp->quit(); } private: QThread mThread; Worker *mWorker; }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Test t; t.start(); return a.exec(); } #include "main.moc"
|
|
|
12
|
Qt / Вопросы новичков / Re: Параллельное заполнение одномерного массива
|
: Декабрь 10, 2017, 03:37
|
Доброго времени суток. Начинаю изучение параллельного программирования. Хотелось бы узнать как, к примеру, можно распараллелить заполнение одномерного массива, допустим случайными числами. При помощи QThread или QtConcurrent. Буду рад любому примеру.
Для поставленной задачи всё просто - делишь массив на кол-во блоков, равному количеству потоков, и в каждом потоке независимо заполняешь нужный блок. Примерно так: C++ (Qt) #include <QCoreApplication> #include <QDebug> #include <QVector> #include <QtConcurrent> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QVector<int> vector; // Для примера массив 10 миллионов значений vector.resize(10000000); QList<QFuture<void>> results; for (int i = 0; i < 10; ++i) { // Получаем указатель на нужный блок int *data = vector.data() + i * 1000000; // запускаем в отдельных потоках заполнялку, указываем лямбде адрес начала блока и его длинну auto result = QtConcurrent::run([i](int *data, const size_t size) { for (int i = 0; i < size; ++i) { *(data++) = qrand(); } // для отладки выводим на экран номер заполненного блока qDebug() << i; }, data, 1000000); // нужно для ожидания окончания заполнения массива results.append(result); } // ждем завершение заполнения массива for (auto &f : results) { f.waitForFinished(); } qDebug() << "end"; return 0; }
|
|
|
|
|