首页 > 编程语言 >VisionPro二次开发学习笔记1-创建基于QuickBuild的C#应用程序

VisionPro二次开发学习笔记1-创建基于QuickBuild的C#应用程序

时间:2024-08-05 13:53:23浏览次数:16  
标签:myJobManager 控件 VisionPro 应用程序 C# Stopped 按钮 二次开发 处理程序

创建基于QuickBuild的C#应用程序

使用的QuickBuild应用程序位于%VPRO_ROOT%/ Samples / Programming / QuickBuild / advancedAppOne.vpp中。在继续之前,可以在QuickBuild中运行该应用程序。

QuickBuild应用程序使用PatMax查找支架的“耳朵”之一,使用CogFixture工具设置图像的坐标空间,使用Blob工具查找两个中心孔,并使用CogDistancePointToPointTool测量孔之间的距离。最后,结果分析工具通过测试两个孔之间的距离是否在可接受的范围内来确定检查是否通过。

该指南分为四个步骤:

  1. 加载QuickBuild应用程序
  2. 添加GUI并使用线程
  3. 增强GUI并显示结果
  4. 显示影像

1.加载QuickBuild应用程序

1. 打开Visual Studio,创建一个C#.NetFramework的Windows应用程序.
2. 添加以下引用
  • Cognex.VisionPro
  • Cognex.VisionPro.Core
  • Cognex.VisionPro.QuickBuild.Core
3. 打开Form1.cs,添加代码如下:
using Cognex.VisionPro;
using Cognex.VisionPro.QuickBuild;
4. 声明变量
private CogJobManager myJobManager;
private CogJob myJob;
private CogJobIndependent myIndependentJob;
5. 在窗体Load事件中加载QuickBuild 应用程序
/// <summary>
/// 从一个文件中加载作业管理器对象。
/// 获取该管理器中的第一个作业。
/// 从该作业中获取与之关联的独立作业。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
        {
            myJobManager = CogSerializer.LoadObjectFromFile(Environment.GetEnvironmentVariable("VPRO_ROOT")+"\\Samples\\Programming\\QuickBuild\\advancedAppOne.vpp") as CogJobManager;

            myJob = myJobManager.Job(0);
            myIndependentJob = myJob.OwnedIndependent;

            //确保队列为空:
            //在加载一个 VisionPro 持久化文件时,需要确保所有队列都是空的。这是因为加载的过程会精确地重建保存时的对象状态。如果在加载过程中队列中仍然保留着未处理的数据,这可能会导致不一致或错误的行为。
            //冲洗队列:
            //“冲洗所有队列”意味着清空所有待处理的数据,以确保系统在加载新的作业或状态时处于一个干净的状态。这种做法是为了避免在处理新数据时与旧数据发生冲突,从而确保系统的稳定性和可靠性。
            myJobManager.UserQueueFlush();
            myJobManager.FailureQueueFlush();
            myJob.ImageQueueFlush();
            myIndependentJob.RealTimeQueueFlush();
        }
6. 关闭

QuickBuild 应用程序的 CogJobManager 对象在运行时会创建多个线程。关闭 CogJobManager 是非常重要的。

当窗体关闭时,将调用 Form1_FormClosing 方法。

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {            
            myJobManager.Shutdown();
        }

2. 添加GUI并使用线程

1. 创建一次运行按钮

您将添加的第一个用户界面元素是运行已保存的QuickBuild应用程序的按钮。在Visual Studio工具箱中,将“按钮”从“公共控件”部分拖到Form1。将此按钮命名为RunOnceButton并将其文本设置为Run一次。

双击按钮以创建其Click处理程序,然后键入以下代码:

private void RunOnceButton_Click(object sender, EventArgs e)
        {
            try
            {
                
                myJobManager.Run();
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

Run方法在myJobManager中运行所有作业,其中包含已保存的QuickBuild应用程序。按钮的Click处理程序在Try / Catch块内调用Run,以处理QuickBuild应用程序开始运行时可能发生的任何错误。

立即运行程序,然后单击“运行一次”按钮以运行应用程序。(由于此时您未显示任何输出,因此您将看不到任何内容。)尝试尽快重复单击RunOnce按钮。您应该收到一条错误消息。

2. 处理作业事件

快速单击“运行一次”按钮时出现错误的原因是“运行”是立即返回的异步方法。如果在作业运行时再次调用它。您会收到CogNotStoppedException错误。

为避免此问题,您将在作业运行时禁用“运行一次”按钮,并在作业停止时重新启用它。在作业开始时禁用按钮非常容易。您所需要做的就是禁用其Click处理程序中的按钮:

private void RunOnceButton_Click(object sender, EventArgs e)
        {
            try
            {
                RunOnceButton.Enabled = false;
                
                myJobManager.Run();
            }
            catch (Exception ex)
            {

                MessageBox.Show(ex.Message);
            }
        }

在作业停止运行时重新启用按钮会稍微复杂一些。当作业管理器中的所有作业均已完成运行时,CogJobManager会触发Stopped事件。您将把代码重新放入作业管理器的Stopped事件处理程序中的按钮。

在Form1类的末尾,为作业管理器编写Stopped处理程序,如下所示:

private void MyJobManager_Stopped(object sender, CogJobManagerActionEventArgs e)
        {
           
            RunOnceButton.Enabled = true;
            
        }

定义了Stopped事件处理程序后,需要确保作业管理器知道它在哪里。使用AddHandler注册事件的处理程序。AddHandler的第一个参数是事件;第二个参数是处理程序的地址。将以下代码添加到Form1_Load方法的末尾:

 //注册停止事件
            myJobManager.Stopped += MyJobManager_Stopped;

每当您注册事件处理程序时,最好在关闭程序之前将其删除。在此示例中,执行此操作的最佳位置是在关闭作业管理器之前的窗体的FormClosing处理程序中。现在,FormClosing处理程序应如下所示:

 private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            myJobManager.Stopped -= MyJobManager_Stopped;
           
            myJobManager.Shutdown();

        }

如果此时运行程序,则会出现错误:跨线程操作无效。

3.处理跨线程函数调用

请记住,作业管理器会创建多个线程。这些线程之一触发运行已停止事件处理程序的Stopped事件,并最终尝试重新启用“运行一次”按钮。此事件序列是非法的,因为按钮-或任何其他Microsoft Windows Forms控件-只能由创建该控件的线程访问。该按钮不是由任何作业管理器线程创建的。

Microsoft提供了一种对控件进行线程安全调用的方法。

注意:您可以在此MDSN文章中了解有关进行线程安全调用的更多信息。

每个控件都有一个InvokeRequired属性,如果正在从未创建控件的线程中调用它,则该属性返回True。如果为True,则必须创建一个指向将访问该控件的函数的指针,切换到创建该控件的线程,然后使用该指针再次调用该函数。

在.NET中,指向函数的指针是委托。您将声明一个与您要处理的事件具有相同功能签名(参数)的委托。在这种情况下,您的委托人具有与Stopped事件相同的签名。在Stopped事件处理程序之前添加以下代码行:

private delegate void myJobManagerDelegate(object sender,CogJobManagerActionEventArgs e);

现在,在Stopped事件处理程序中,您将检查是否从错误的线程调用了该处理程序。如果是这样,则将使用定义的委托创建指向处理程序的指针,然后使用Invoke方法以递归方式调用它。这是Stopped事件处理程序的外观:

 private void MyJobManager_Stopped(object sender, CogJobManagerActionEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myJobManagerDelegate(MyJobManager_Stopped),new object[] { sender,e});
                return;
            }
            RunOnceButton.Enabled = true;
            
        }

3. 增强GUI并显示结果

1. 添加连续运行按钮

您将添加的下一个用户界面元素是“运行连续”按钮。当您单击此按钮时,它将保持按下状态,并且该应用程序将运行,直到再次单击该按钮。若要获得此行为,本示例使用一个复选框并将其外观更改为按钮。

确保Form1.cs [设计]选项卡处于活动状态。从Visual Studio工具箱的“公共控件”部分中,将一个CheckBox控件拖到窗体上。将其文本更改为“连续运行”。将其名称更改为RunContCheckBox。最后,将其外观更改为Button。

双击新的“连续运行”按钮以创建其Check_Changed处理程序,并添加以下代码:

private void RunContentCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            if (RunContentCheckBox.Checked)
            {
                try
                {
                    
                    myJobManager.RunContinuous();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            else
            {
                try
                {
                    
                    myJobManager.Stop();
                }
                catch (Exception ex)
                {

                    MessageBox.Show(ex.Message);
                }
            }
            
        }

RunContinuous方法重复运行myJobManager中的所有作业,该作业包含您保存的QuickBuild应用程序,直到Stop停止它们为止。CheckedChanged处理程序负责在作业开始时禁用“运行一次”按钮,并在等待作业停止时禁用“连续运行”按钮。

将以下代码行添加到“已停止”处理程序中,以在所有作业停止后重新启用“连续运行”按钮。

 private void MyJobManager_Stopped(object sender, CogJobManagerActionEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myJobManagerDelegate(MyJobManager_Stopped),new object[] { sender,e});
                return;
            }
            RunOnceButton.Enabled = true;
            RunContentCheckBox.Enabled = true;
        }

并将以下代码行添加到“运行一次”按钮的单击处理程序,以在作业运行一次时禁用“运行连续”按钮。

RunContentCheckBox.Enabled = false;

如果此时运行程序,则会在适当的时间看到按钮变为启用和禁用状态。您也可以单击窗口的关闭框以退出应用程序,即使该应用程序正在运行。

2. 显示程序结果

当用户队列中有新结果可用时,作业管理器将触发UserResultAvailable事件。在那儿,您将从工作中提取数据并将其显示在表单中。

确保Form1.cs [设计]选项卡处于活动状态。从Visual Studio工具箱的“公共控件”部分中,将一个TextBox拖到您的窗体上。将其名称更改为RunStatusTextBox。在这里您将显示应用程序的运行状态。

在Form1类的末尾,添加以下UserResultAvailable事件处理程序。请注意,由于它修改了用户界面项(文本框),因此您需要使用之前学习的Invoke习惯用法。

 private void MyJobManager_UserResultAvailable(object sender, CogJobManagerActionEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myJobManagerDelegate(MyJobManager_UserResultAvailable), new object[] { sender, e });
                return;
            }
            ICogRecord topRecord = myJobManager.UserResult();
            RunStatusTextBox.Text = topRecord.SubRecords["UserResultTag"].Content + ":" + topRecord.SubRecords["JobName"].Content + "-->" + topRecord.SubRecords["RunStatus"].Content.ToString();

           
        }

UserResult方法从作业管理器的用户队列中删除并返回最早的结果记录。该记录包含“已发布项目”列表中每个项目的子记录。(请参阅配置过帐项目清单。)它还包含这些其他子记录:

UserResultTag

作业运行的序列号
职位名称

返回结果的作业的名称
运行状态

作业的RunStatus

在运行程序之前,您需要在窗体的Load处理程序中注册UserResultsAvailable处理程序,然后在其FormClosing处理程序中注销它。现在,Load处理程序应如下所示:

private void Form1_Load(object sender, EventArgs e)
        {
            myJobManager = CogSerializer.LoadObjectFromFile(Environment.GetEnvironmentVariable("VPRO_ROOT")+"\\Samples\\Programming\\QuickBuild\\advancedAppOne.vpp") as CogJobManager;

            myJob = myJobManager.Job(0);
            myIndependentJob = myJob.OwnedIndependent;

            //确保队列为空:
            //在加载一个 VisionPro 持久化文件时,需要确保所有队列都是空的。这是因为加载的过程会精确地重建保存时的对象状态。如果在加载过程中队列中仍然保留着未处理的数据,这可能会导致不一致或错误的行为。
            //冲洗队列:
            //“冲洗所有队列”意味着清空所有待处理的数据,以确保系统在加载新的作业或状态时处于一个干净的状态。这种做法是为了避免在处理新数据时与旧数据发生冲突,从而确保系统的稳定性和可靠性。
            myJobManager.UserQueueFlush();
            myJobManager.FailureQueueFlush();
            myJob.ImageQueueFlush();
            myIndependentJob.RealTimeQueueFlush();

            //注册停止事件
            myJobManager.Stopped += MyJobManager_Stopped;
            myJobManager.UserResultAvailable += MyJobManager_UserResultAvailable;

            


        }

FormClosing处理程序如下所示:

//取消注册与 myJobManager 相关的事件处理程序,以避免在窗体关闭后接收事件。
        //调用 Application.DoEvents() 来处理任何挂起的消息,确保在执行后续操作(如关闭作业管理器)时,应用程序不会冻结。
        //调用 myJobManager.Shutdown() 方法以正确清理资源和停止后台任务。
        //使用 DoEvents() 可以确保在执行 Shutdown 操作之前,所有与用户界面相关的事件都得到处理,从而提高用户体验。尽管 DoEvents() 在某些情况下有其用途,但在大多数情况下,过度使用可能会导致复杂性增加,因此应谨慎使用。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            myJobManager.Stopped -= MyJobManager_Stopped;
            myJobManager.UserResultAvailable -= MyJobManager_UserResultAvailable;
            Application.DoEvents();
            myJobManager.Shutdown();

           
        }

除了删除UserResultAvailable处理程序外,FormClosing方法还调用Application.DoEvents()来清除Windows消息队列。它可以防止在单击表单的关闭框之后但未注册UserResultAvailable处理程序之前,如果有新的用户结果可用,则可能发生死锁。

3. 运行应用程序

运行应用程序时,您将在文本框中看到结果。在下一步中,您将在应用程序中添加一个显示。

4. 显示图像

  • 使用显示控件显示结果记录
  • 访问适当的记录以显示
  • 将显示状态栏连接到显示器
1. 显示控件概述

VisionPro提供了四种显示控件,可用于显示图像和图形。

显示控制描述
CogToolDisplay这是您在QuickBuild和视觉工具中看到的显示控件。您可以将VisionPro工具连接到显示控件,并直接从该工具提取记录。它使用下拉列表选择要显示的图像记录。
CogRecordsDisplay此控件类似于CogToolDisplay控件。它使用户可以从下拉列表中选择图像记录,并显示图像的任何图形子记录。与CogToolDisplay不同,此控件对VisionPro工具一无所知。您必须提供要显示的记录。
CogRecordDisplay该控件显示单个图像记录及其图形子记录。它没有下拉列表框,并且不允许用户选择图像。
CogDisplay这是所有其他显示控件用作基础的最低级别的显示控件。此控件显示单个图像和一组图形,这些图形必须直接提供给该控件。

在此示例中,您将使用CogRecordDisplay控件显示LastRun.CogFixtureTool1.OutputImage记录,其中包含括号的图像以及显示孔之间距离的图形。

添加对以下程序集的引用:

  • Cognex.VisionPro.Controls
  • Cognex.VisionPro.Display.Controls

确保Form1.cs [设计]选项卡处于活动状态。从Visual Studio工具箱的VisionPro显示控件部分中,将CogRecordDisplay控件拖到窗体上。

注意:如果在工具箱中看不到CogRecordDisplay,请在工具箱中单击鼠标右键,然后选择“选择项目”。在出现的“选择工具箱项”对话框中,向下滚动直到找到CogRecordDisplay并确保已选中该复选框。

在FormClosing方法的末尾,添加以下代码以在应用程序关闭时处置控件:

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            myJobManager.Stopped -= MyJobManager_Stopped;
            myJobManager.UserResultAvailable -= MyJobManager_UserResultAvailable;
            Application.DoEvents();
            myJobManager.Shutdown();

            cogDisplayStatusBarV21.Dispose();
            cogRecordDisplay1.Dispose();
        }

然后在Load方法的末尾添加以下代码,以将显示状态栏与显示器链接起来。

private void Form1_Load(object sender, EventArgs e)
        {
            myJobManager = CogSerializer.LoadObjectFromFile(Environment.GetEnvironmentVariable("VPRO_ROOT")+"\\Samples\\Programming\\QuickBuild\\advancedAppOne.vpp") as CogJobManager;

            myJob = myJobManager.Job(0);
            myIndependentJob = myJob.OwnedIndependent;

            //确保队列为空:
            //在加载一个 VisionPro 持久化文件时,需要确保所有队列都是空的。这是因为加载的过程会精确地重建保存时的对象状态。如果在加载过程中队列中仍然保留着未处理的数据,这可能会导致不一致或错误的行为。
            //冲洗队列:
            //“冲洗所有队列”意味着清空所有待处理的数据,以确保系统在加载新的作业或状态时处于一个干净的状态。这种做法是为了避免在处理新数据时与旧数据发生冲突,从而确保系统的稳定性和可靠性。
            myJobManager.UserQueueFlush();
            myJobManager.FailureQueueFlush();
            myJob.ImageQueueFlush();
            myIndependentJob.RealTimeQueueFlush();

            //注册停止事件
            myJobManager.Stopped += MyJobManager_Stopped;
            myJobManager.UserResultAvailable += MyJobManager_UserResultAvailable;

            cogDisplayStatusBarV21.Display = cogRecordDisplay1;


        }

获取记录以显示在CogRecordDisplay控件中的代码位于UserResultAvailable处理程序的末尾:

private void MyJobManager_UserResultAvailable(object sender, CogJobManagerActionEventArgs e)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myJobManagerDelegate(MyJobManager_UserResultAvailable), new object[] { sender, e });
                return;
            }
            ICogRecord topRecord = myJobManager.UserResult();
            RunStatusTextBox.Text = topRecord.SubRecords["UserResultTag"].Content + ":" + topRecord.SubRecords["JobName"].Content + "-->" + topRecord.SubRecords["RunStatus"].Content.ToString();

            ICogRecord tmpRecord = topRecord.SubRecords["ShowLastRunRecordForUserQueue"];
            tmpRecord = tmpRecord.SubRecords["LastRun"];
            tmpRecord = tmpRecord.SubRecords["CogFixtureTool1.OutputImage"];
            cogRecordDisplay1.Record = tmpRecord;
            cogRecordDisplay1.Fit(true);
        }

对SubRecords的连续调用遵循子记录路径,以获取QuickBuild应用程序的Fixture工具的输出图像。Record属性指定要显示的记录。Fit方法缩放图像及其图形以适合显示控件。

界面设计如下:

在这里插入图片描述

如果立即运行该程序,您将看到CogRecordDisplay控件中显示的每个图像。

![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=image-1.png&pos_id=img-Fx41UDRR-1722836446552在这里插入图片描述

在这里插入图片描述

标签:myJobManager,控件,VisionPro,应用程序,C#,Stopped,按钮,二次开发,处理程序
From: https://blog.csdn.net/qq_44082700/article/details/140924822

相关文章

  • Minoxidil (U10858) 是一种ATP 敏感性钾 (KATP) 通道开启剂 |MedChemExpress (MCE)
    中文名:米诺地尔CAS:38304-91-5品牌:MedChemExpress(MCE)存储条件:Powder:-20°C,3years;4°C,2years.Insolvent:-80°C,6months;-20°C,1month.生物活性:Minoxidil(U10858)是一种ATP敏感性钾(KATP)通道 开启剂,是一种有效的口服降压药和外周血管扩张剂,可促......
  • Spring Cloud 学习笔记四:服务网关(Gateway)
    在微服务架构中,随着服务数量的增加,客户端直接与服务进行通信的方式会变得越来越复杂。为了简化客户端与服务之间的交互,同时实现一些跨服务的通用功能(如认证、限流、监控等),SpringCloud引入了服务网关(Gateway)的概念。本篇文章将详细介绍SpringCloudGateway的基本概念、使......
  • PlayCover Mac电脑全屏运行ios应用软件 for Mac免费下载
    PlayCover是一款功能强大的软件,主要用于在Mac平台上运行iOS应用程序和Android应用程序(取决于具体版本)。对于iOS应用,PlayCover通过模拟iOS环境,让用户能够在Mac上直接运行iPhone和iPad应用,无需虚拟机或双重启动,支持多点触控、传感器模拟等特性,提供舒适的使用体验。对于Android应用,P......
  • ctf_web_sql
    1,union联合注入(1)万能密码and优先级高于or,先执行and;则username="用户提交"andpassword="1"为假;or后面的条件恒为真;则where条件为真;输出admin表中所有的信息select*fromadminwhereusername="用户提交"andpassword="1"or"1"="1"bp万能密......
  • 解决|RuntimeWarning: invalid value encountered in double_scalars W = numer / d
    报错:RuntimeWarning:invalidvalueencounteredindouble_scalarsW=numer/denom我自查发现代码包含levene和t检验部分,且涉及多步除法。一旦分母为0或NaN就会出现上述报错在chatgpt帮我过了一遍所有可能的分母时,发现就两种情况:1-样本数异常(为0或为1——自由度为0),我的数......
  • Echarts 实现圆角环形图
     第一种方式:使用bar实现想要的效果:代码实现:constchartData={title:{text:'97',//圆环中间数字textStyle:{color:'#222222',fontSize:20,},subtext:'成功数',subtextS......
  • SciTech-BigDataAI-ImageProcessing-OpenCV-Splitting and Merging Channels with Ope
    Links:https://pyimagesearch.com/2021/01/23/splitting-and-merging-channels-with-opencv/OpenCVOfficial:https://docs.opencv.org/3.4/d3/df2/tutorial_py_basic_ops.htmlSplittingandMergingImageChannelsSometimesyouwillneedtoworkseparatelyonth......
  • 打卡信奥刷题(506)用Scratch图形化工具信奥P1614[普及组/提高组] 爱与愁的心痛
    爱与愁的心痛题目背景(本道题目隐藏了两首歌名,找找看哪~~~)《爱与愁的故事第一弹·heartache》第一章。《我为歌狂》当中伍思凯神曲《舞月光》居然没赢给萨顶顶,爱与愁大神心痛啊~~~而且最近还有一些令人伤心的事情,都让人心痛(最近真的很烦哈)……题目描述最近有......
  • 深入理解 Scikit-Learn 中的 fit, transform 和 fit_transform
    #深入理解Scikit-Learn中的fit,transform和fit_transform在使用Scikit-Learn进行数据处理和机器学习建模时,经常会遇到三个重要的方法:`fit`、`transform`和`fit_transform`。它们是Scikit-Learn中用于数据预处理、特征提取和模型训练的核心方法。本文将详细解释这......
  • 安装CPU版本的TensorFlow教程
    在这篇博客中,我将详细介绍如何在Conda虚拟环境中安装CPU版本的TensorFlow。第一步,首先在安装前你需要检查你的电脑中是否安装VisualStudio,在应用中搜索visual,如下图,如果有就跳到下一步,没有的话就跟着下面步骤安装。 VisualStudio安装,复制链接到浏览器打开,选择适合你电脑......