QImage 和线程

2024-02-16

我在使用 QImage 和 Qthread 时遇到问题。 我正在尝试在线程中加载大图像,然后将它们显示为 QLabel 上的 QPixmap。 我的问题是,只要我不使用不同的线程来加载 QImage,一切都是完美的,但是一旦我使用不同的线程,渲染器就什么也没有了。 尽管我的 QImage 仍然有有效的尺寸。

让我困惑的是,如果我只注释 cpp 中将加载程序移动到另一个线程的第 22 行,标签就会很好地显示。

有人有想法吗?

这是我非常简化的代码: 标题:

class Loader : public QObject
{
    Q_OBJECT
public:
    explicit Loader(QObject *parent = 0);

signals:
    void imageLoaded(QString, const QImage &);
public slots:
    void loadImage(const QString& fichier);
};

namespace Ui {
class MainWindow;
}
class LoaderImages;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

signals:
    void loadImage(const QString& dossier);
private slots:
    void imageAvailable(const QString& dossier, const QImage& img);

private:
    Ui::MainWindow *ui;
    //QString mDossier;
    Loader* mLoader;
    //QMap<QString, QImage*> mMapDesImages;
    int mWidth;
};

cpp:

#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);
}

Thx!


有几个错误:

  1. 你没有显示标签。当图像加载器位于 GUI 线程中时,将加载图像并将标签添加到内容窗格中before显示主窗口。由于显示了父级,因此子级也可见。

    当加载在另一个线程中完成时,您将向已显示的小部件添加图像标签。这样的子部件是not除非你明确地可见show() them.

  2. 你正在泄露图像loadImage。没有理由这么说QImage在堆上。

  3. 你允许跑步QThread被摧毁。这是一个常见的错误,因为QThread本质上是被设计破坏的。 Sane C++ 类应该始终是可破坏的。QThread不是。因此你需要一个解决方法。

  4. 你没有设置最小值height内容小部件也是如此。

  5. 您可能希望考虑使用QtConcurrent::run而不是专用线程。当您正在进行的操作或多或少是一次性操作时,这一点尤其值得。我已经展示了这两种实现,它们的实现在运行时交替。请注意,您需要添加concurrent模块和CONFIG += c++11到项目文件。

  6. 风格错误:

    • 没有理由为已经为零的默认值参数传递 NULL。

    • 没有理由保留QObject具有堆上父对象生命周期的成员(如果此类成员与父对象一起构造)。

    • 仅仅因为 Qt Creator 附带了愚蠢的模板文件并不意味着您不应该使用std::unique_ptr or 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"
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QImage 和线程 的相关文章

  • 检查目录是否为空

    我正在尝试检查目录是否为空 MainWindow MainWindow QWidget parent QMainWindow parent ui new Ui MainWindow ui gt setupUi this QDir Dir h
  • 我的 QSqlQueryModel 不在列表视图中显示数据

    我正在玩 QSqlQueryModel 但我现在完全陷入困境 我一整天都在寻找解决方案 但到目前为止还没有运气 我所做的工作是它从我的 sqlite 数据库中提取数据 但由于某种原因我无法在列表视图中显示它 我的角色名似乎不存在 对于我从数
  • [本机]:在Qt for Android中使用Java函数和第3方库[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 最近我用qt写了一个android应用程序 但我有一个很大的问题 我可以使用 调用一些原生的android API 比如调用特殊的activit
  • 调整 QML 图像显示尺寸

    我有一个带有嵌套的 QML 窗口RowLayout 在内排我有两个图像 来源 png这些图像的文件 故意 相当大 当我尝试设置height这些图像上的属性使它们变小 但它们仍然被画得很大 Desired Appearance Actual
  • pyqtgraph ImageView 在多线程时冻结

    我有多个通过 WiFi 无线连接的摄像头 我正在尝试将数据流式传输到客户端 客户端在 GUI 上显示流 我的问题是 pyqtgraph ImageItems 似乎在大约 30 秒后停止重新绘制 或者如果我单击窗口外 或者如果我调整其中一张图
  • QT 中只获取文件而不获取目录?

    当我这样做时 QDir myDir home some location QStringList filesList myDir entryList 它返回该位置内的文件和目录 但我只想要文件 并且这些文件可以具有任意扩展名 有任何想法吗
  • Qt 支持在 QIcon 中为 SVG 着色

    看来 Qt 不支持 SVG 中路径标签上的描边 填充选项
  • QTableView 中的虚拟列?

    我开始学习 Qt4 模型 视图编程 我有初学者问题 我有一个简单的应用程序 其中显示 sqlite 表QTableView class Model QtSql QSqlTableModel def init self parent None
  • MAC 上的 QT/C++ - 未设置应用程序图标

    我正在努力解决的奇怪问题 在与我的 pro QT 项目文件相同的文件夹中 我有一个 Resources myIcon png 我试图将其设置为我构建的应用程序的图标 在 OSX 上运行 我阅读了文档 它建议在 pro 文件中添加 ICON
  • 从 QML 实例化 C++ 对象会产生巨大的内存使用开销

    实例化一个QObjectC 堆中的派生类为每个对象提供了大约 160 个字节 通过注册相同的对象qmlRegisterType 用于从 QML 创建并通过以下方式动态创建对象createObject 每个对象给我 2000 多个字节 这是完
  • 为什么下面的重叠比较总是评估为 true

    我不明白为什么以下代码有警告 指出重叠比较始终评估为真 接下来的语句永远不会被执行 QVariant MainModel data const QModelIndex index int role const if index isVali
  • 仅将非模态 QDialog 窗口放置在我的应用程序顶部,而不是所有应用程序顶部

    我有一个 QDialog 窗口 它应该始终位于我的应用程序顶部 它不是模态的 用户可以随时与对话框和主应用程序进行交互 使用窗口保持在顶部提示在某种程度上实现了这一点 但是 该对话框仍然位于所有其他正在运行的应用程序 例如记事本 chrom
  • QGraphicsScene::clear 不会改变 sceneRect

    我有一个 QGraphicsScene 场景 和 QGraphicsView graphicsView 我有一个画图的方法 当我需要重绘所有图形时 我调用这个方法 一切都好 但我意识到 scene gt clear 不会改变 sceneRe
  • 如何创建用于 QML 的通用对象模型?

    我想知道是否有任何宏或方法如何将 Qt 模型注册为 QObject 的属性 例如 我有AnimalModel http doc qt io qt 5 qtquick modelviewsdata cppmodels html qabstra
  • QCombobox 向下箭头图像

    如何更改Qcombobox向下箭头图像 现在我正在使用这个 QSS 代码 但这不起作用 我无法删除向下箭头边框 QComboBox border 0px QComboBox down arrow border 0px background
  • 更改 Qt OpenGL 窗口示例以使用 OpenGL 3.3

    我正在尝试更改 Qt OpenGL 示例以使用更现代的 opengl 版本 330 似乎合适 所以我做了 在 main cpp 上设置版本和配置文件 设置着色器版本 更改着色器以使用统一 它现在构建没有任何错误 但我只看到一个空白窗口 我错
  • 如何在 QTabWidget Qt 中展开选项卡

    我有一个QTabWidget像这个 但我想展开选项卡以 填充 整个小部件宽度 如下所示 我怎样才能做到这一点 我在用Qt 5 3 2 and Qt 创建者 3 2 1 Update 我尝试使用setExpanding功能 ui gt myT
  • 如何使QTableView类的restoreState()和saveState()正常工作?

    首先 我想说 我的问题已经在这里讨论过 并且这里是 https stackoverflow com questions 1163030 qt qtableview and horizontalheader restorestate 但答案并
  • 即使在可访问性中勾选应用程序,AXIsProcessTrustedWithOptions 也不会返回 true

    As this question https stackoverflow com questions 17693408 enable access for assistive devices programmatically on 10 9
  • QTimer 一点也不准确?

    运行在 Windows7 64 位机器上 具有非常强大的 CPU 8 核 16 线程 我使用 QTimer 以 50Hz 触发函数调用 但我最终得到了 30Hz 函数调用本身肯定需要不到 10 毫秒才能完成 整个过程发生在一个单独的线程中

随机推荐

  • 如何获取 SLURM 作业所用脚本的原始位置?

    我正在使用脚本启动 SLURM 作业 并且脚本必须根据其在脚本本身内部获取的位置来工作SCRIPT LOCATION realpath 0 但 SLURM 将脚本复制到slurmd文件夹并从那里开始工作 这会搞砸进一步的操作 在移动 复制之
  • 桌面上方的浮动图标

    我正在编写一个 C 应用程序 我希望它在桌面上有一个浮动图标 就像移动设备中的 Facebook Messenger 我一直在互联网上搜索但找不到任何有用的东西 有文章吗 有想法吗 您需要创建一个没有标题栏和边框的表单 并使用图像作为表单的
  • OpenCV中概率霍夫变换的具体实现是什么?

    有谁知道 OpenCV 实现中概率霍夫变换的特定算法吗 我的意思是 有关于该算法的参考论文或文档吗 为了得到这个想法 我当然可以查看源代码 但我想知道是否有任何关于它的文档 它不在源代码的注释中 OpenCV 1 0 谢谢你 Jin Ope
  • 是否需要验证或转义jsonp回调字符串

    我有一个名为 action php 的文件 它将执行一些操作 我想将其公开为纯 JSON 或 JSONP 输出 用户将使用如下 URL 来调用它 action php jsonp callback 在我的action php中我正在做这样的
  • 服务器端对云服务执行多个请求

    我正在编写一个使用多个 Web API 的 Web 应用程序 对于单个用户的单个请求 我的应用程序可能需要对其他站点执行最多 30 个 HTTP 请求 包含网络应用程序的网站可以拥有数百个并发用户 我一直在四处寻找 试图找出应该使用哪个库
  • Kubernetes,无法通过 DNS 挂载 NFS 共享

    我正在尝试通过 DNS 查找在我的容器中安装 NFS 共享 k8s 集群外部 我的配置如下 apiVersion v1 kind Pod metadata name service a spec containers name servic
  • 设计模式和架构模式有什么区别? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 当我们读到设计模式在互联网上 我们注意到有 3 类 创作型 结构性 行为的 但是当我们创建软件架构时 我们会考虑 MVP MVC 或
  • 覆盖 Spree Commerce 的 Bootstrap 变量

    我在部署自定义项目时遇到问题 variables scss作为编译资产添加到我的生产服务器 在我的开发环境中一切都很好 在生产中我的变量被覆盖 我正在使用 Rails 4 2 1 和 Spree 3 0 稳定分支 我有以下结构 文件创建于v
  • 如何仅在少数列中插入数据,而其他列为空或像它们在mysql表记录中一样?

    我创建了一个名为 学生 的表 它有以下字段 roll no lt type Integer Not Null course name lt type varchar 40 Not Null std surname lt type varch
  • 实体框架 5 命名空间

    我想首先将 Entity Framework 5 数据库添加到面向 net Framework 4 5 的 Visual Studio 2012 中的类库中 我对需要输入的所有标签感到困惑 将 ADO NET 实体数据模型添加到项目时的 E
  • 裁剪 CMSampleBuffer 并对其进行处理,而不转换为 CGImage

    我一直在关注苹果直播摄像机编辑器 https developer apple com documentation avfoundation cameras and media capture avcamfilter applying fil
  • RESTful API:需要用户代理字符串吗?

    我的团队有一个带有 RESTful API 的网站 我们正在对其进行负载测试 因此我们构建了一个小型控制台应用程序来处理请求 此控制台应用程序不会设置用户代理字符串 这会导致我们的 API 出现错误 因为它是我们数据库中的必填字段 那么 如
  • 服务器端的 Blazor:使用 MongoDB 进行身份管理

    VS 2019 中的 Asp Net Core Blazor 模板可以创建一个服务器端应用程序 该应用程序将使用 Microsoft SQL Server 来管理帐户和声明以进行身份 管理 我想用MongoDB而不是用于账户和索赔管理 这样
  • UILocalNotification 自定义 soundName 仅在指定alertBody 时振动手机(与 UILocalNotificationDefaultSoundName 不同)?

    我有一个 VoIP 应用程序 当应用程序在后台时 它使用 UILocalNotification 通知用户有来电 当出现通知时 我希望它多次播放声音并振动手机 并且不会重复显示相同的消息 我能够通过使用一系列通知来做到这一点 第一个通知会立
  • cx_Oracle & 远程连接到 Oracle DB

    如何通过 IP 地址连接到远程服务器 就像 TOAD SqlDeveloper 能够仅使用 IP 地址 用户名 SID 和密码连接到数据库一样 每当我尝试指定 IP 地址时 它似乎都是在本地获取的 换句话说 cx Oracle connec
  • 如何将AOP引入到生产性软件开发中?

    我知道这个问题以前曾被问过 但这是一年半前的事了 尽管我认为现在可能是重新提问的时候了 我也认识到它可能被视为主观的 但我认为支持 反对 AOP 是有客观原因的 我有兴趣谁在使用AOP在软件开发中也why or why not使用它 我认为
  • 使用 jquery 触发 ul 标签点击事件而不是 li

    如何使用 jQuery 只影响 ul 标签而不影响所有 li 的点击事件 ul class wrap li test1 li li test2 li li test3 li ul 我尝试过像这样使用jquery 但它不起作用 Javascr
  • 如何增加基于手机或平板电脑浏览器的网页中的复选框大小?

    我为手机 平板电脑设计了一个网页 当我在手机 平板电脑浏览器中打开它时 复选框看起来很小 很难识别它是否被选中 我尝试过使用CSS 但没有用 我们如何增加手机 平板电脑浏览器网页的复选框大小 还有什么解决办法吗 try
  • (iOS 10、Swift 3)从 CloudKit 通知中读取 `userInfo` 字典:如何将 `[AnyHashable : Any]` 转换为 `[String : NSObject]`?

    背景 我正在尝试加载userInfo字典来自application didReceiveRemoteNotification userInfo fetchCompletionHandler在我的应用程序委托中 然后我需要投射userInfo
  • QImage 和线程

    我在使用 QImage 和 Qthread 时遇到问题 我正在尝试在线程中加载大图像 然后将它们显示为 QLabel 上的 QPixmap 我的问题是 只要我不使用不同的线程来加载 QImage 一切都是完美的 但是一旦我使用不同的线程 渲