qt多次调用函数显示多张图片

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了qt多次调用函数显示多张图片相关的知识,希望对你有一定的参考价值。

参考技术A 01. 概述

QT与Halcon联合编程。将Halcon中代码集成到Qt程序中。

开发环境

Qt:Qt5.15.2

Halcon: Halcon 19.11

02. 编写Halcon程序

Halcon程序示例

* 从本地磁盘读取一张图片
read_image (Carb, 'E:/CarB.jpg')

* 获取图片大小
get_image_size (Carb, Width, Height)

* 关闭当前窗口
dev_close_window ()

* 打开新窗口
dev_open_window (0, 0, Width / 2, Height / 2, 'black', WindowHandle)

* 显示图片
dev_display (Carb)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Halcon中执行结果
请添加图片描述

03. Halcon程序导出C++文件

将上述Halcon程序导出为C++源程序

导出内容如下:

///
// File generated by HDevelop for HALCON/C++ Version 19.11.0.0
// Non-ASCII strings in this file are encoded in local-8-bit encoding (cp936).
// Ensure that the interface encoding is set to locale encoding by calling
// SetHcppInterfaceStringEncodingIsUtf8(false) at the beginning of the program.
//
// Please note that non-ASCII characters in string constants are exported
// as octal codes in order to guarantee that the strings are correctly
// created on all systems, independent on any compiler settings.
//
// Source files with different encoding should not be mixed in one project.
///

#ifndef __APPLE__
# include "HalconCpp.h"
# include "HDevThread.h"
#else
# ifndef HC_LARGE_IMAGES
# include <HALCONCpp/HalconCpp.h>
# include <HALCONCpp/HDevThread.h>
# include <HALCON/HpThread.h>
# else
# include <HALCONCppxl/HalconCpp.h>
# include <HALCONCppxl/HDevThread.h>
# include <HALCONxl/HpThread.h>
# endif
# include <stdio.h>
# include <CoreFoundation/CFRunLoop.h>
#endif

using namespace HalconCpp;

// Procedure declarations
// Local procedures
void blobImage (HObject *ho_Image, HObject *ho_Region);

// Procedures
// Local procedures
void blobImage (HObject *ho_Image, HObject *ho_Region)


ReadImage(&(*ho_Image), "E:/test.jpg.tif");

Threshold((*ho_Image), &(*ho_Region), 128, 255);

if (HDevWindowStack::IsOpen())
DispObj((*ho_Image), HDevWindowStack::GetActive());

if (HDevWindowStack::IsOpen())
DispObj((*ho_Region), HDevWindowStack::GetActive());
return;


#ifndef NO_EXPORT_MAIN
// Main procedure
void action()


// Local iconic variables
HObject ho_Carb;

// Local control variables
HTuple hv_Width, hv_Height, hv_WindowHandle;

//从本地磁盘读取一张图片
ReadImage(&ho_Carb, "E:/CarB.jpg");

//获取图片大小
GetImageSize(ho_Carb, &hv_Width, &hv_Height);

//关闭当前窗口
if (HDevWindowStack::IsOpen())
CloseWindow(HDevWindowStack::Pop());

//打开新窗口
SetWindowAttr("background_color","black");
OpenWindow(0,0,hv_Width/2,hv_Height/2,0,"visible","",&hv_WindowHandle);
HDevWindowStack::Push(hv_WindowHandle);

//显示图片
if (HDevWindowStack::IsOpen())
DispObj(ho_Carb, HDevWindowStack::GetActive());



#ifndef NO_EXPORT_APP_MAIN

#ifdef __APPLE__
// On OS X systems, we must have a CFRunLoop running on the main thread in
// order for the HALCON graphics operators to work correctly, and run the
// action function in a separate thread. A CFRunLoopTimer is used to make sure
// the action function is not called before the CFRunLoop is running.
// Note that starting with macOS 10.12, the run loop may be stopped when a
// window is closed, so we need to put the call to CFRunLoopRun() into a loop
// of its own.
HTuple gStartMutex;
H_pthread_t gActionThread;
HBOOL gTerminate = FALSE;

static void timer_callback(CFRunLoopTimerRef timer, void *info)

UnlockMutex(gStartMutex);


static Herror apple_action(void **parameters)

// Wait until the timer has fired to start processing.
LockMutex(gStartMutex);
UnlockMutex(gStartMutex);

try

action();

catch (HException &exception)

fprintf(stderr," Error #%u in %s: %s\n", exception.ErrorCode(),
(const char *)exception.ProcName(),
(const char *)exception.ErrorMessage());


// Tell the main thread to terminate itself.
LockMutex(gStartMutex);
gTerminate = TRUE;
UnlockMutex(gStartMutex);
CFRunLoopStop(CFRunLoopGetMain());
return H_MSG_OK;


static int apple_main(int argc, char *argv[])

Herror error;
CFRunLoopTimerRef Timer;
CFRunLoopTimerContext TimerContext = 0, 0, 0, 0, 0 ;

CreateMutex("type","sleep",&gStartMutex);
LockMutex(gStartMutex);

error = HpThreadHandleAlloc(&gActionThread);
if (H_MSG_OK != error)

fprintf(stderr,"HpThreadHandleAlloc failed: %d\n", error);
exit(1);


error = HpThreadCreate(gActionThread,0,apple_action);
if (H_MSG_OK != error)

fprintf(stderr,"HpThreadCreate failed: %d\n", error);
exit(1);


Timer = CFRunLoopTimerCreate(kCFAllocatorDefault,
CFAbsoluteTimeGetCurrent(),0,0,0,
timer_callback,&TimerContext);
if (!Timer)

fprintf(stderr,"CFRunLoopTimerCreate failed\n");
exit(1);

CFRunLoopAddTimer(CFRunLoopGetCurrent(),Timer,kCFRunLoopCommonModes);

for (;;)

HBOOL terminate;

CFRunLoopRun();

LockMutex(gStartMutex);
terminate = gTerminate;
UnlockMutex(gStartMutex);

if (terminate)
break;


CFRunLoopRemoveTimer(CFRunLoopGetCurrent(),Timer,kCFRunLoopCommonModes);
CFRelease(Timer);

error = HpThreadHandleFree(gActionThread);
if (H_MSG_OK != error)

fprintf(stderr,"HpThreadHandleFree failed: %d\n", error);
exit(1);


ClearMutex(gStartMutex);
return 0;

#endif

int main(int argc, char *argv[])

int ret = 0;

try

#if defined(_WIN32)
SetSystem("use_window_thread", "true");
#endif

// file was stored with local-8-bit encoding
// -> set the interface encoding accordingly
SetHcppInterfaceStringEncodingIsUtf8(false);

// Default settings used in HDevelop (can be omitted)
SetSystem("width", 512);
SetSystem("height", 512);

#ifndef __APPLE__
action();
#else
ret = apple_main(argc,argv);
#endif

catch (HException &exception)

fprintf(stderr," Error #%u in %s: %s\n", exception.ErrorCode(),
(const char *)exception.ProcName(),
(const char *)exception.ErrorMessage());
ret = 1;

return ret;


#endif

#endif

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
04. 创建Qt图形界面项目

4.1 简单的GUI设计如下
请添加图片描述

集成halcon编译需要用msvc,如果用minGW,会出错,等有时间在去研究minGW编译情形。

05. Qt集成Halcon程序

5.1 在pro项目配置文件中添加一下Halcon相关配置

# MacOS specific settings. Note that while dyld will search under
# /Library/Frameworks by default, the preprocessor/compiler/linker will not
# and need to be told explicitly.
macx
QMAKE_CXXFLAGS += -F/Library/Frameworks
QMAKE_LFLAGS += -F/Library/Frameworks
LIBS += -framework HALCONCpp

else
#defines
win32:DEFINES += WIN32

#includes
INCLUDEPATH += "$$(HALCONROOT)/include"
INCLUDEPATH += "$$(HALCONROOT)/include/halconcpp"

#libs
QMAKE_LIBDIR += "$$(HALCONROOT)/lib/$$(HALCONARCH)"
unix:LIBS += -lhalconcpp -lhalcon -lXext -lX11 -ldl -lpthread
win32:LIBS += "$$(HALCONROOT)/lib/$$(HALCONARCH)/halconcpp.lib" \
"$$(HALCONROOT)/lib/$$(HALCONARCH)/halcon.lib"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
5.2 在mainwindow.h文件中添加Halcon相关头文件

#ifndef __APPLE__
# include "HalconCpp.h"
# include "HDevThread.h"
#else
# ifndef HC_LARGE_IMAGES
# include <HALCONCpp/HalconCpp.h>
# include <HALCONCpp/HDevThread.h>
# include <HALCON/HpThread.h>
# else
# include <HALCONCppxl/HalconCpp.h>
# include <HALCONCppxl/HDevThread.h>
# include <HALCONxl/HpThread.h>
# endif
# include <stdio.h>
# include <CoreFoundation/CFRunLoop.h>
#endif

using namespace HalconCpp;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
5.3 在MainWindow添加halcon相关的变量
请添加图片描述

源程序如下:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#ifndef __APPLE__
# include "HalconCpp.h"
# include "HDevThread.h"
#else
# ifndef HC_LARGE_IMAGES
# include <HALCONCpp/HalconCpp.h>
# include <HALCONCpp/HDevThread.h>
# include <HALCON/HpThread.h>
# else
# include <HALCONCppxl/HalconCpp.h>
# include <HALCONCppxl/HDevThread.h>
# include <HALCONxl/HpThread.h>
# endif
# include <stdio.h>
# include <CoreFoundation/CFRunLoop.h>
#endif

using namespace HalconCpp;

QT_BEGIN_NAMESPACE
namespace Ui class MainWindow;
QT_END_NAMESPACE

class MainWindow : public QMainWindow

Q_OBJECT

public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();

private slots:
void on_pushButton_clicked();

void on_pushButton_3_clicked();

private:
Ui::MainWindow *ui;

// Local iconic variables
HObject ho_Carb;

// Local control variables
HTuple hv_Width, hv_Height, hv_WindowHandle;

;
#endif // MAINWINDOW_H

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
5.4 实现采集图像槽函数

//采集图像
void MainWindow::on_pushButton_clicked()


QString fileName = QFileDialog::getOpenFileName(this,
tr("打开图片"), "E://", tr("Image Files (*.png *.jpg *.bmp)"));

qDebug() << fileName;
//从本地磁盘读取一张图片

//QString转HTuple要通过String
ReadImage(&ho_Carb, fileName.toStdString().c_str());

//获取图片大小
GetImageSize(ho_Carb, &hv_Width, &hv_Height);


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
友情提示

//QString转HTuple要通过String
ReadImage(&ho_Carb, fileName.toStdString().c_str());
5.5 实现显示图像槽函数

//显示图像
void MainWindow::on_pushButton_3_clicked()

//关闭当前窗口
if (HDevWindowStack::IsOpen())
CloseWindow(HDevWindowStack::Pop());

//打开新窗口
SetWindowAttr("background_color","black");
OpenWindow(0,0,hv_Width/2,hv_Height/2, (Hlong)ui->label->winId(),"visible","",&hv_WindowHandle);
HDevWindowStack::Push(hv_WindowHandle);

//显示图片
if (HDevWindowStack::IsOpen())
DispObj(ho_Carb, HDevWindowStack::GetActive());

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
友情提示

Qt中winId()和Halcon中窗口句柄转换
OpenWindow(0,0,hv_Width/2,hv_Height/2, (Hlong)ui->label->winId(),“visible”,"",&hv_WindowHandle);
5.6 编译程序

运行结果如下:
请添加图片描述

06. 附录

6.1 测试程序下载

下载:【机器视觉】Qt联合Halcon编程之显示多图片.rar
参考技术B qt多次调用函数显示多张图片解决办法如下:
断开槽函数链接 只显示一遍;若要循环播放,改为 img_index=0 即可 三、资源 完整工程代码(vs2015/qt5.10.0

LayUI上传图片(文件)的时候,上传多张图片(文件)会调用多次接口,而我们想要让上传多个文件的时候只调用一次接口,怎么解决?

文章目录

LayUI上传图片(文件)的时候,上传多张图片(文件)会调用多次接口,而我们想要让上传多个文件的时候只调用一次接口,怎么解决?

如何把调用多次接口改为调用一次接口

现在出现了一个问题,我们在前端上传图片的时候想要上传多张图片,我们想要让它只访问一次接口,给我们后端传递一个文件集合对象,但是现在出现的问题是,我们如果在LayUi前端页面上传多个图片,结果会调用多次接口,并且每个接口传递给我们后端的参数只有一个文件,不是多个文件,如下图:

后端代码如下图:

看一下我们的layui是怎么写的,如下图:

所以这就会出现一个问题了,因为我们上传多张图片的时候,我们调用接口是一个一个接着调用的,所以你上传几个图片,那么我们就会调用多次次url代表的接口,那怎么解决呢?

我们上传图片的时候不要自动上传,如下图:

我们把所有的上传图片一次性获取到,封装到formData对象里面,然后调用一次ajax方法,如下图:

前端使用LayUi如何上传文件

html:

<button class="layui-btn" id="upload" type="button">
                               <i class="layui-icon">&#xe67c;</i>上传图片
                           </button>

js:

$(function () 
        layui.use(['upload','form'], function () 
            var upload = layui.upload;
            var form = layui.form;

            var files;
            upload.render(
                    elem: '#upload'
                    ,before(res) 
                       console.log(res);
                    
                    ,allDone: function(obj) //当文件全部被提交后,才触发
                       console.log(obj.total); //得到总文件数
                       console.log(obj.successful); //请求成功的文件数
                       console.log(obj.aborted); //请求失败的文件数
                       console.log(obj);
                    
                    ,multiple: true
                    ,number: 4
                    ,size: 5120 //图片上传的大小最大为5M
                    ,exts: "jpg|png|jpeg"
                    ,auto: false  //选定文件后不自动上传
                    ,choose: (obj) => 
                       files = obj.pushFile();
                    
            )

            form.on('submit(submitForm)',function (data) ``
                console.log(files);
                var formData = new FormData();
                for(let  i in files)
                    formData.append("files",files[i]);
                
                $.ajax(
                    type:'POST',
                    url: "/complaint/uploadImage",
                    data: formData,
                    processData: false,
                    contentType: false,
                    async: false,
                    dataType: "json",
                    success: function(result)
                        console.log(result);
                    
                );


            );

        );
    );

后端如何接收前端传递来的多个文件

如下图:

 @RequestMapping(value = "/uploadImage",method = RequestMethod.POST)
    @ResponseBody
    public JSONArray uploadImage(@RequestParam(value = "files") List<MultipartFile> files) throws IOException 
        //该json数组用来存放微信返回给我们的上传图片所对应的id
        JSONArray jsonArray = new JSONArray();

        //商户上传反馈图片API  地址
        String uri = "https://api.mch.weixin.qq.com/v3/merchant-service/images/upload";

        //遍历前端传递过来的图片,并且访问微信官方接口,把返回的图片id封装到一个json数组里面
        if(files != null && files.size()>0)
            for(int i=0;i<files.size();i++)
                MultipartFile file = files.get(i);

                //上传到这个文件夹
                String filePath = "D:/image";
                File filePathOther = new File(filePath);
                //如果没有的话创建一个文件夹
                if (!filePathOther.exists()) 
                    filePathOther.mkdirs();
                

                //文件全路径
                //路径+文件名
                //文件名:file.getOriginalFilename()
                String finalFilePath = filePath + "/" + file.getOriginalFilename().trim();
                //查看目录中是否已经存在该文件
                File desFile = new File(finalFilePath);
                //如果目录中不存在上传的文件,则直接在目录中下载文件
                if (!desFile.exists()) 
                    //把上传文件存储到该目录中
                    file.transferTo(desFile);
                

                //把文件的全路径传递给微信“上传商户图片API接口”
                try 
                    String mediaId = HttpClientUtil.uploadImg(finalFilePath, uri, testMchId, testMchSerialNo, testApiV3Key, testPrivateKey);
                    jsonArray.add(mediaId);
                 catch (Exception e) 
                    log.error("WeiXinComplaintController中的uploadImage方法调用微信官方接口出错");
                    e.printStackTrace();
                
            
        

        return jsonArray;
    

前端页面图

以上是关于qt多次调用函数显示多张图片的主要内容,如果未能解决你的问题,请参考以下文章

LayUI上传图片(文件)的时候,上传多张图片(文件)会调用多次接口,而我们想要让上传多个文件的时候只调用一次接口,怎么解决?

LayUI上传图片(文件)的时候,上传多张图片(文件)会调用多次接口,而我们想要让上传多个文件的时候只调用一次接口,怎么解决?

Qt的自定义类调用show函数不能显示布局,就像图片上显示一样

微信jssdk多图上传

Qt如何全屏显示图片

Qt paintEvent事件 显示图片文字