Qt QImage和线程
我在QImages和Qthreads方面有问题。 我试图在线程中加载大图像,然后在QLabel上显示为QPixmap。 我的问题是,只要我不使用不同的线程来加载QImages,一切都是完美的,但只要我使用不同的线程,就没有什么是渲染器。 虽然我的QImage还有一个有效的尺寸 让我困惑的是,如果我只是注释cpp中将加载程序移动到另一个线程的第22行,标签就会显示得很好 有人有主意吗 下面是我非常简化的代码: 标题: 类加载器:公共QObject { Q_对象 公众: 显式加载器(QObject*parent=0); 信号: 无效图像加载(QString、const QImage&); 公众时段: void loadImage(常量QString和fichier); }; 名称空间用户界面{ 类主窗口; } 类装入器图像; 类主窗口:公共QMainWindow { Q_对象 公众: 显式主窗口(QWidget*parent=0); ~main窗口(); 信号: 无效加载映像(常量字符串和档案); 专用插槽: 无效图像可用(常量字符串和档案、常量图像和img); 私人: Ui::MainWindow*Ui; //QString-mDossier; 装载机*mLoader; //QMap-mMapDesImages; 国际宽度; }; cpp:Qt QImage和线程,qt,qthread,Qt,Qthread,我在QImages和Qthreads方面有问题。 我试图在线程中加载大图像,然后在QLabel上显示为QPixmap。 我的问题是,只要我不使用不同的线程来加载QImages,一切都是完美的,但只要我使用不同的线程,就没有什么是渲染器。 虽然我的QImage还有一个有效的尺寸 让我困惑的是,如果我只是注释cpp中将加载程序移动到另一个线程的第22行,标签就会显示得很好 有人有主意吗 下面是我非常简化的代码: 标题: 类加载器:公共QObject { Q_对象 公众: 显式加载器(QObject*
#包括“mainwindow.h”
#包括“ui_main window.h”
#包括
#包括
#包括
#包括
#包括
#包括
#包括
主窗口::主窗口(QWidget*父窗口):
QMainWindow(父级),
ui(新ui::主窗口),
mLoader(新加载程序(NULL)),
mWidth(0)
{
用户界面->设置用户界面(此);
QThread*thread=新的QThread(此);
mLoader->moveToThread(线程);
线程->开始();
连接(此,信号(loadImage(QString)),mLoader,插槽(loadImage(QString));
连接(mLoader,SIGNAL(imageload(QString,QImage)),此,插槽(imageAvailable(QString,QImage));
发出loadImage(“C:/img.jpg”);
}
无效主窗口::图像可用(常量字符串和档案、常量图像和img)
{
mWidth+=(img.width()+20);
ui->mScrollContent->setMinimumSize(mWidth,img.height());
QLabel*lab=新的QLabel(ui->mScrollContent);
lab->setFixedSize(img.width(),img.height());
lab->setGeometry(mWidth-img.width()+20,0,img.width(),img.height());
lab->setPixmap(QPixmap::frommage(img));
}
MainWindow::~MainWindow()
{
删除mLoader;
删除用户界面;
}
加载器::加载器(QObject*父对象):
QObject(父对象)
{
}
无效加载程序::加载映像(常量QString和fichier)
{
QImage*image=新的QImage(fichier);
发射图像加载(菲希尔,*图像);
}
谢谢 有几个错误:
show()
这些子窗口小部件,否则它们是不可见的loadImage
中泄漏图像。没有理由把QImage
放在堆上QThread
。这是一个常见的错误,因为QThread
基本上被设计破坏了。明智的C++类应该总是可破坏的。代码>QThread不是。因此,您需要一个变通方法concurrent
模块和CONFIG+=c++11
添加到项目文件中
- 对于已经为零的默认值参数,没有理由传递NULL
- 如果将具有父对象生存期的
成员与父对象一起构造,则没有理由在堆上保留这些成员QObject
- 仅仅因为Qt Creator附带了愚蠢的模板文件,并不意味着您不应该使用
或std::unique_ptr
来保存QScopedPointer
成员。裸指针几乎不应该是成员,除非它们是指向父对象的ui
QObjects
// https://github.com/KubaO/stackoverflown/tree/master/questions/image-loader-24853687
#include <QtWidgets>
#include <QtConcurrent>
class Thread final : public QThread {
public:
~Thread() { quit(); wait(); }
};
class Loader : public QObject
{
Q_OBJECT
public:
explicit Loader(QObject *parent = nullptr) : QObject(parent) {}
Q_SIGNAL void imageLoaded(const QString &, const QImage &);
Q_SLOT void loadImage(const QString& fichier) {
QImage img(fichier);
if (! img.isNull()) emit imageLoaded(fichier, img);
}
};
class MainWindow : public QWidget
{
Q_OBJECT
Loader m_loader;
Thread m_loaderThread;
QGridLayout m_layout{this};
QPushButton m_open{"Open"};
QScrollArea m_view;
QWidget m_content;
int m_width{};
bool m_threadImpl = true;
Q_SIGNAL void loadImage(const QString &);
Q_SIGNAL void imageLoaded(const QString &, const QImage & img);
Q_SLOT void imageAvailable(const QString &, const QImage & img) {
int spacing = 20;
if (m_width) m_width += spacing;
auto lab = new QLabel(&m_content);
lab->setFixedSize(img.width(), img.height());
lab->setGeometry(m_width, 0, img.width(), img.height());
lab->setPixmap(QPixmap::fromImage(img));
lab->show();
m_width += img.width();
m_content.setMinimumWidth(m_width);
m_content.setMinimumHeight(qMax(m_content.minimumHeight(), img.height()));
}
Q_SLOT void open() {
auto dialog = new QFileDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
if (m_threadImpl)
connect(dialog, &QFileDialog::fileSelected, this, &MainWindow::loadImage);
else
connect(dialog, &QFileDialog::fileSelected, [this](const QString & fichier){
QtConcurrent::run([this, fichier]{
QImage img(fichier);
if (! img.isNull()) emit this->imageLoaded(fichier, img);
});
});
m_threadImpl = !m_threadImpl;
}
public:
explicit MainWindow(QWidget *parent = nullptr) : QWidget(parent) {
m_layout.addWidget(&m_open);
m_layout.addWidget(&m_view);
m_view.setWidget(&m_content);
m_loader.moveToThread(&m_loaderThread);
m_loaderThread.start();
connect(&m_open, &QPushButton::clicked, this, &MainWindow::open);
connect(this, &MainWindow::loadImage, &m_loader, &Loader::loadImage);
connect(this, &MainWindow::imageLoaded, this, &MainWindow::imageAvailable);
connect(&m_loader, &Loader::imageLoaded, this, &MainWindow::imageAvailable);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#include "main.moc"
//https://github.com/KubaO/stackoverflown/tree/master/questions/image-loader-24853687
#包括
#包括
类线程final:publicqthread{
公众:
~Thread(){quit();wait();}
};
类加载器:公共QObject
{
Q_对象
公众:
显式加载程序(QObject*parent=nullptr):QObject(parent){}
Q_信号无效图像加载(常量QString&,常量QImage&);
Q_插槽无效加载映像(常量QString&fichier){
QImage img(菲希尔);
如果(!img.isNull())发出imageLoaded(fichier,img);
}
};
类主窗口:公共QWidget
{
Q_对象
装载机m_装载机;
线程m_loaderThread;
QGridLayout m_布局{this};
QPushButton m_open{“open”};
QScrollArea m_视图;
qm_内容;
int m_width{};
bool m_threadImpl=true;
Q_信号无效载荷图像(常数QString&);
已加载Q_信号无效图像(常数Q字符串和、常数Q图像和img);
Q_插槽无效映像可用(常量QString和、常量QImage和img){
整数间距=20;
如果(m_宽度)m_宽度+=间距;
自动实验室=新的QLabel(&m_内容);
lab->setFixedSize(img.width(),img.height());
lab->setGeometry(m_width,0,img.width(),img.height());
lab->setPixmap(QPixmap::frommage(img));
实验室->显示();
穆维
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFile>
#include <QPixmap>
#include <QImage>
#include <QDir>
#include <QThread>
#include <QDebug>
#include <QLabel>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
mLoader(new Loader(NULL)),
mWidth(0)
{
ui->setupUi(this);
QThread* thread = new QThread(this);
mLoader->moveToThread(thread);
thread->start();
connect(this, SIGNAL(loadImage(QString)), mLoader, SLOT(loadImage(QString)));
connect(mLoader, SIGNAL(imageLoaded(QString,QImage)), this, SLOT(imageAvailable(QString,QImage)));
emit loadImage("C:/img.jpg");
}
void MainWindow::imageAvailable(const QString &dossier, const QImage& img)
{
mWidth += (img.width() + 20);
ui->mScrollContent->setMinimumSize(mWidth,img.height());
QLabel* lab = new QLabel(ui->mScrollContent);
lab->setFixedSize(img.width(), img.height());
lab->setGeometry(mWidth - img.width() + 20, 0, img.width(), img.height());
lab->setPixmap(QPixmap::fromImage(img));
}
MainWindow::~MainWindow()
{
delete mLoader;
delete ui;
}
Loader::Loader(QObject *parent) :
QObject(parent)
{
}
void Loader::loadImage(const QString& fichier)
{
QImage* image = new QImage(fichier);
emit imageLoaded(fichier, *image);
}
// https://github.com/KubaO/stackoverflown/tree/master/questions/image-loader-24853687
#include <QtWidgets>
#include <QtConcurrent>
class Thread final : public QThread {
public:
~Thread() { quit(); wait(); }
};
class Loader : public QObject
{
Q_OBJECT
public:
explicit Loader(QObject *parent = nullptr) : QObject(parent) {}
Q_SIGNAL void imageLoaded(const QString &, const QImage &);
Q_SLOT void loadImage(const QString& fichier) {
QImage img(fichier);
if (! img.isNull()) emit imageLoaded(fichier, img);
}
};
class MainWindow : public QWidget
{
Q_OBJECT
Loader m_loader;
Thread m_loaderThread;
QGridLayout m_layout{this};
QPushButton m_open{"Open"};
QScrollArea m_view;
QWidget m_content;
int m_width{};
bool m_threadImpl = true;
Q_SIGNAL void loadImage(const QString &);
Q_SIGNAL void imageLoaded(const QString &, const QImage & img);
Q_SLOT void imageAvailable(const QString &, const QImage & img) {
int spacing = 20;
if (m_width) m_width += spacing;
auto lab = new QLabel(&m_content);
lab->setFixedSize(img.width(), img.height());
lab->setGeometry(m_width, 0, img.width(), img.height());
lab->setPixmap(QPixmap::fromImage(img));
lab->show();
m_width += img.width();
m_content.setMinimumWidth(m_width);
m_content.setMinimumHeight(qMax(m_content.minimumHeight(), img.height()));
}
Q_SLOT void open() {
auto dialog = new QFileDialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->show();
if (m_threadImpl)
connect(dialog, &QFileDialog::fileSelected, this, &MainWindow::loadImage);
else
connect(dialog, &QFileDialog::fileSelected, [this](const QString & fichier){
QtConcurrent::run([this, fichier]{
QImage img(fichier);
if (! img.isNull()) emit this->imageLoaded(fichier, img);
});
});
m_threadImpl = !m_threadImpl;
}
public:
explicit MainWindow(QWidget *parent = nullptr) : QWidget(parent) {
m_layout.addWidget(&m_open);
m_layout.addWidget(&m_view);
m_view.setWidget(&m_content);
m_loader.moveToThread(&m_loaderThread);
m_loaderThread.start();
connect(&m_open, &QPushButton::clicked, this, &MainWindow::open);
connect(this, &MainWindow::loadImage, &m_loader, &Loader::loadImage);
connect(this, &MainWindow::imageLoaded, this, &MainWindow::imageAvailable);
connect(&m_loader, &Loader::imageLoaded, this, &MainWindow::imageAvailable);
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#include "main.moc"