显示标签为“编程”的博文。显示所有博文
显示标签为“编程”的博文。显示所有博文

2015年7月15日星期三

最好的"关于什么是回调函数"问题的解答

今天在翻stackoverflow,看到一条解答,差点笑喷,实在牛逼,史上最好的关于什么是回调函数Callback的解释(links),如果你熟悉,Carly Rae Jepsen的Call me maybe这首歌。


2015年5月12日星期二

关于C#连接local database的方法

今天就上一图 关于C#连接local database的方法,这图中包括了代码和VS 2012上如何找到Connection String的方法。


2015年5月11日星期一

使用Emgu CV不要忘记加入OpenCV Libs

记录一个小经验。使用的是Emgu CV 2.410版本,如果编译CameraCapture这样的小程序,我们需要Emgu.CV.dll,Emgu.CV.UI.dll和Emgu.Util.dll加入Project的Reference中去。这样就可以执行这个小程序。



有时候在VS2012中运行编译后的程序有可能会出现上图所示这个问题,可能的原因 1. 没有OpenCV Libs,如果编译成x86,我们就需要把x86的目录放入Debug和Build生成exe的文件夹里面,可以x86这个文件夹从C:\Emgu\bin里面找到。2 也有可能设置Debug和Build的路径问题,只需要确认是否正确设置就可以了。

2015年5月6日星期三

C++中的vector快速拷贝

今天编程中发现新写的程序运行速度很低,经过一番查找才发现是的vector拷贝的效率问题。

//[1] 方法1
vector vec = vec_src;

//[2] 方法2
vector vec(vec_src);

//[3] 方法3
vector vec(vec_src.size());
std::copy( vec_src.begin(), vec_src.end(), vec.begin() );

// 使用的是OpenCV的方法用来测试运行的时间
double t = (double)getTickCount();
t = ((double)getTickCount() - t)/getTickFrequency();
// some codes
cout << "Times passed in milli seconds: " << t * 1000 << endl;

方法3最快,在我的笔记本上用VS2012在32bit中居然比第一种和第二种方法快近10倍,当然了也可以使用memcpy,但是其效率不会比std::copy高多少。

2014年12月23日星期二

关于CLR的runtime的一个小记录

如果在.NET项目中使用Common Language Runtime Support (/clr)编译C++项目,如下图所示,如果使用VS2012会默认使用,.NET framework 4.5:



如果我们使用引用这个通过CLR编译的dll,查看它的属性,也会发现,如下图所示的,这个dll的Runtime Version是v4.0319。



如果我们的项目使用的不是.NET framework 4.5,使用上面所述的CLR编译的项目中的namespace就会出现下面的报错:
Error 492 The type or namespace name 'XXX' could not be found (are you missing a using directive or an assembly reference?)
最简单的解决的方法就是修改我们项目的Target Framework,将其改为4.5就可以了。

2014年9月11日星期四

使用QNetworkAccessManager下载文件的一个问题

今天发现一个问题,使用Qt的QNetworkAccessManager进行下载,将其放入一个QPushButton的clicked()的slots,但是无法正确执行下载文件,想了半天,还是没有搞明白,最后在stackoverflow在找到这个问题的解决方法,才明白,因为QNetworkAccessManager是非同步的,它需要一个event loop去开始下载,而我们执行clicked()这个slots,它会给一个control back给event loop,但是QNetworkAccessManager以及被销毁了,没有时间去做QNetworkAccessManager的下载文件。

解决方法:如果加入一个QMessageBox,这样就会启动另一个event loop在这个slot里面,这样QNetworkAccessManager就会有机会完成下载文件这个工作。

链接:
http://stackoverflow.com/questions/7870017/how-can-i-download-file-from-the-internet-in-qt

2014年9月8日星期一

OpenCV放大或者缩小图像的速度

使用OpenCV放大或者缩小图像,我们比较熟悉的是下面的function:
cv::resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )¶
http://docs.opencv.org/modules/imgproc/doc/geometric_transformations.html
关于它的Interpolation method(插值方法),其中:

INTER_NEAREST 最近邻插值,是最快的method并且创建blocky images并选择1个pixel去替代几个pixels,这样做得到图像的结果效果比较差。
INTER_AREA 也是一个快速计算方法,它取几个pixels的平均值,所以它比较适合缩小图像,而不是放大图像。
INTER_LINEAR 使用双线性的插值去改变图像尺寸,组成几个pixels在一起(在很多情况下是比较好的选择,但是计算速度比较慢)。
INTER_CUBIC 使用的是双三次的插值,但是计算机量比较大,所以运行速度慢,而且有时候结果看起来比较好,有时候比较差。

非常简单地,不完全正确地说,在速度上:
INTER_NEAREST > INTER_AREA > INTER_LINEAR > INTER_CUBIC
但是放大或者缩小图像后的效果上一般而言INTER_LINEAR是相对最好的。

其实,也可以使用Opencv的cv::pyrUp(使用Gaussian 金字塔分解对输入图像向上采样)和cv::pyrDown(使用 Gaussian金字塔分解对输入图像向下采样),关于使用这两个function去放大或者缩小图像,具体信息可查阅下面链接:
http://docs.opencv.org/doc/tutorials/imgproc/pyramids/pyramids.html
但是cv::pyrUp和cv::pyrDown的运算速度其实也并不高。

2014年9月7日星期日

libVLC进行memory stream延迟问题

最近我使用libVLC进行在server端进行memory stream,出现了一个问题,client端得到的视频有7秒的延迟。类似以下帖子提到的问题:
http://stackoverflow.com/questions/19604815/main-input-error-and-delays-when-libvlc-stream-images-in-memory

为了找到错误我打开以下的参数:
"--verbose=2", // Be much more verbose then normal for debugging purpose
这样可以得到更多的debug信息。
我得到这样的信息:main warning: late buffer for mux input

经过查阅发现,正确的解决方法就是,在transcode里设置venc=x264{preset=ultrafast,tune=zerolatency}这样的参数:

sprintf(smem_options_transcode,"#transcode{venc=x264{preset=ultrafast,tune=zerolatency},acodec=none}:rtp{mux=ts,dst=127.0.0.1,port=5004}");

这样延迟可以控制在3秒以内,当然了,可以使用其他的方法进一步减少延迟,譬如在client端减少caching的数值等等。

解决方法参考:
https://forum.videolan.org/viewtopic.php?f=4&t=95364

2014年8月19日星期二

Qt Webkit 加入新的plugin路径

在Qt中使用QWebView播放flash文档(swf格式),需要加入NPSWF32.dll这个plugin,如果使用plugin要使用下面代码,去允许使用plugin:

QWebSettings *settings = QWebSettings::globalSettings();

settings->setAttribute (QWebSettings::PluginsEnabled, true);

但是如果还是无法显示flash文档,其实原因是Qt无法找到正确的plugin路径,需要使用类似以下代码,告诉Qt正确的含有NPSWF32.dll的plugin路径:

QString path  = QDir::currentPath() + "/webplugins";

qputenv("QTWEBKIT_PLUGIN_PATH", path.toLocal8Bit());

2014年6月25日星期三

重新写一个精简的核心库

最近的带的项目陷入了软件开发的危机,原因是陷入自家写的库造成的泥沼越来越深。

最近几年带的大的软件项目都是使用自家写的库,工具库utils,开发库commDev,核心库core,api库,可视化库viz等等。当然了使用自家的库开发软件有时候非常有效率,但是自家开发库的升级以及维护绝对是一个大问题,维护超过5万行程序本身就是一个大问题,而且这几年来因为项目压力,常常直接将很多东西放入核心库core里,导致核心库臃肿不堪,而且关于库的使用的实例程序以及接口或者api更本做不到时常更新,有很多文档已经四五年了,更本无法使用,所以导致最最大的痛苦是教新人使用我们的库。更为恐怖的是核心库对其他外部库的依赖越来越多,从OpenCV,Boost到现在的至少10个以上的第三方库,但是核心库更本也没有根据外部库进行更新,至今核心库还在使用OpenCV2.0。更为痛苦的是自家写的库还是使用VS2008进行编译,因为实在太大,以至于没有人有勇气进行修整,并使用最新的编译器进行编译。


现在实在受不了了,我终于决定重写核心库,并且放弃工具库utils,开发库commDev,api库,可视化库viz。新的核心库只有两个依赖OpenCV和Qt这两个第三方库的巨无霸。放弃的工具库utils,开发库commDev,api库,可视化库viz,全部使用Qt代替。新的核心库就叫CoreLite,只依赖于最新的Qt5.3和OpenCV2.49,保持绝对的精简,而且可以根据Qt和OpenCV的升级进行编译,而且使用VS2012进行开发和编译,希望能做到根据OpenCV更新的频率进入版本更新。

  • 新的库CoreLite的第一个tag就是CoreLite290,使用和OpenCV一样的文档结构。
    \build\include
    \build\x86 (\build\x86\vc11\bin, \build\x86\vc11\lib)
    \sources\modules\
  • 新的库使用Qt的QThread。
  • 控制Class的总数,只包括Qt或OpenCV无法提供的一些特性,例如Producer-Comsumer-Data Sink结构。
  • 带几个实例。
  • 保证库的可读性,使用Qt的api的写作标准。
  • 最大程度保证库的可维护性,其实就是要保持精简。

目前想到的就是这些了,以后在重新的过程中,如果还有什么想法,我希望能写下来记录一下,期望可以用一个星期将新的核心库改写完成。

2014年6月14日星期六

VS 2008编译的程序部署的一个问题解决

最近遇到一个问题,在一台机器上使用VS 2008编译的程序无法在其他机器上运行,马上想到了以前提到过的关于Side-by-Side问题, 但是安装了Microsoft Visual C++ 2008 SP1 Redistributable Package (x86)后程序还是无法运行,而且没有什么错误信息。然后使用Windows里的Computer Management里的Event Viewer的Windows Logs发现这个程序无法运行的原因在于其调用的一个动态链接库DLL。然后我查看了一下这个DLL的Manifest,原来多了一个Microshoft.VC90.DebugCRT的依赖,如下图所示。如果我们在机器上没有安装VS 2008当然就会没有Microshoft.VC90.DebugCRT的依赖需要的msvcm90d.dll,msvcp90d.dll,msvcr90d.dll,所以程序就无法运行了。

manifest_vs2008_debug
解决的方法就是使用在release模式下编译,或者如下图所示,修改C++ Project的Property里的Linker-->Debugging选项页,将Generate Debug Info修改成No,将Debuggable Assembly改成No Debuggable attribute emitted,原来如下图a所示,修改后如下图b所示:

debuggable_assembly_debug_modedebuggable_assembly_release_mode

现在再编译一次,查看一下新生成的DLL的Manifest可以发现Microshoft.VC90.DebugCRT的依赖已经没有了,现在程序应该可以在其他机器上运行了。

manifest_vs2008_release

2014年1月27日星期一

Emgu CV使用1

最近开始使用Emgu CV,也就是在.NET可以使用的OpenCV,Emgu CV是一个.Net的wrapper。使用从C++转到C#中写OpenCV代码,开始时候还真的很不习惯,以下将简单整理一下最近的一些笔记。

如何将Grayimage转换到Matrix<float>,注意rows cols和height width的关系:

Image<Gray, float> img = new Image<Gray, float>("c:\\test_image.jpg");
int rows = img.Height;
int cols = img.Width;
Matrix<float> tmp_matrix= new Matrix<float>(rows, cols);
CvInvoke.cvConvert(img, tmp_matrix);
       

如何显示图:

//The name of the window
String win1 = "Test Window";
//Create the window using the specific name
CvInvoke.cvNamedWindow(win1);
Image<Bgr, Byte> img = new Image<Bgr, Byte>("c:\\test_image.jpg");
CvInvoke.cvShowImage(win1, img.Ptr);
//Wait for the key pressing event
CvInvoke.cvWaitKey(1);
//Destory the window
CvInvoke.cvDestroyWindow(win1);
           

如何画一个正方形在图上:

Rectangle box = new Rectangle(121, 57, 75, 97);
Image<Bgr, Byte> img = new Image<Bgr, Byte>("c:\\test_image.jpg");
img.Draw(box, new Bgr(Color.DarkOrange), 2);

如何计算一个积分图integral image,在C++中我们可以使用integral(frame, imageIntegral, CV_32F),在C#中可以这样做:

Image<Gray, double> cvImageIntegral = null;
cvImageIntegral = frame.Integral();

如何计算标准差,标准差就是方差的算术平方根,反映组内个体间的离散程度,标准差与期望值之比为标准离差率。

Matrix<float> mat = ... // your input matrix
MCvScalar average = new MCvScalar();
MCvScalar std = new MCvSaclar();
CvInvoke.cvAvgSdv(mat, ref average, ref std, IntPtr.Zero);

2013年11月28日星期四

转换QImage到FFmpeg的internal YUV format

今天正巧有时间,在家里修改并整理一下我3年前写的视频播放和储存代码。FFmpeg更新非常快,突然发现我还在使用2011年09月23日的FFmpeg版本。最新版本已经到了2.1.1(http://ffmpeg.zeranoe.com/builds/win32/dev/),刚刚下载了,试着编译以前写的代码,发现很多API都变了,无法编译了,懒得再进行调整了,放弃使用新版本了,新的特性暂时用不到。我将2011年09月23日的FFmpeg版本作为项目的标准lib,打包上传到服务器上,还有SVN里。

刚刚在修改“转换QImage到FFmpeg的internal YUV format的方法”,这个方法是从QtFFmpegWrapper项目抄来的,https://code.google.com/p/qtffmpegwrapper/。我发现,我刚刚写的新代码中使用的是QImage::Format_RGB888,如果直接使用这个方法转换的frame就会不正确,是黑白的而且尺寸也不对,想了一下,其实只需要将ffmpeg::sws_getCachedContext这个API里的Source PixelFormat 改成PIX_FMT_RGB24就行了,简单而言只要注意将QImage的PixelFormat和AVFrame的PixelFormat正确对应就行了,具体代码如下面所示。

void convertImage_sws(const QImage &img)
{
   // Check if the image matches the size
   if(img.width() != getWidth() || img.height() != getHeight())
   {
      printf("Wrong image size!\n");
      return false;
   }
   if(img.format() != QImage::Format_RGB32 && img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_RGB888)    
   {
      printf("Wrong image format\n");
      return false;
   }

   //img_convert_ctx = ffmpeg::sws_getCachedContext(img_convert_ctx, getWidth(), getHeight(),
      // ffmpeg::PIX_FMT_BGRA, getWidth(),getHeight(), ffmpeg::PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);

   img_convert_ctx = ffmpeg::sws_getCachedContext(img_convert_ctx, getWidth(), getHeight(),  ffmpeg::PIX_FMT_RGB24,  getWidth(), getHeight(), ffmpeg::PIX_FMT_YUV420P,  SWS_BICUBIC,  NULL,  NULL,  NULL);

   if (img_convert_ctx == NULL)
   {
      printf("Cannot initialize the conversion context\n");
      return false;
   }

   uint8_t *srcplanes[3];
   srcplanes[0] = (uint8_t*)img.bits();
   srcplanes[1] = 0;
   srcplanes[2] = 0;

   int srcstride[3];
   srcstride[0] = img.bytesPerLine();
   srcstride[1] = 0;
   srcstride[2] = 0;

   ffmpeg::sws_scale(img_convert_ctx, srcplanes, srcstride, 0, getHeight(), ppicture->data, ppicture->linesize);

   return true;
}

2013年11月26日星期二

开始使用C++/CLI编程

一直以来一直是使用C++和C#,最近接触了C++/CLI并开始使用它编写程序,已经写了两三千行程序,使用C++/CLI对一个C++和C#程序员来说简直是轻而易举,C++/CLI也会给我们带来很多好处,有了C++/CLI对于.NET平台上的C++来说就是多了一个非常好用的武器,C++在.NET平台中得到极大的补充,所谓“C++/CLI”是静态C++对象模型到CLI的动态组件对象编程模型的捆绑。简而言之就是如何用C++在·NET中编程,而不是C#或Visual Basic,它实现了ISOC++和.NET的无缝连接。像C#和CLI本身一样符合ISO标准。微软的.NET的基础CLR(Common Language Runtime,通用语言运行时)就是CLI的一个实例。
百度百科,维基百科:
http://baike.baidu.com/view/459502.htm?noadapt=1
http://zh.wikipedia.org/wiki/C%2B%2B/CLI

以下内容转载自《C++/CLI in action》

The Common Language Infrastructure (CLI) is an architecture that supports a dynamic language-independent programming model based on a Virtual Execution System.

The role of C++/CLI

role of c   cli

C++ has been paired with language extensions before, and the result hasn’t always been pretty. Visual C++ 2005 is the first version of a Microsoft C++ compiler that has implemented the C++/CLI specification. This means three things for the C++ developer:
■ C++ can be used to write applications that run on the .NET Framework. There is no need to learn a totally new language or to abandon all the C++ knowledge and experience built up through years of coding.
■ C++/CLI lets developers reuse their native C++ code base, saving the agony of having to rewrite all the existing code to enable it to run on the .NET Framework.
■ C++/CLI is designed to be the lowest-level language for the .NET Framework. For writing purely managed applications, it’s your most powerful choice; or, as I like to say, “C++/CLI actually lets you smell the CLR (Common Language Runtime).”


C++/CLI. C++ with some additional keywords and semantics that support .NET
One of the core aspects of the CLR is a unified type system called the Common Type System (CTS). The CTS defines the model followed by the CLR for the declaration and usage of CLI types.

hierarchy of NET frameworkThe common language specification

What is the .NET Framework?
The .NET Framework provides an abstraction layer on top of the native operating system that allows applications compiled into a special intermediate language called Microsoft Intermediate Language (MSIL) to run under a managed environment— where both execution and memory are managed by various parts of the framework. Its two primary components are the Common Language Runtime (CLR) and an extensive Base Class Library (BCL). The CLR is responsible for the execution of .NET applications, inducing memory management through its built-in Garbage Collector (see the section on memory management for more information), whereas the BCL provides various hierarchical class libraries for creating rich user interfaces (UIs), both for the desktop and for the Web—accessing data, security, web services, and many more commonly-performed programming chores.

2013年11月21日星期四

TwinCAT 3使用记录2:ADS介绍

今天简要地介绍一下ADS和一个简单的实际例程。ADS就是Automation Device Specification,通过使用Beckhoff的ADS接口可以和一些virtual Automation Device或者是Windows的程序相连。如果安装了TwinCAT3可以在C:\TwinCAT\AdsApi\TcAdsDll\Lib\找到TcAdsDll.lib,这就是我们需要的ADS的lib文件。对于ADS接口,最重要的操作就是READ和WRITE了,以下是API的说明。

long __stdcall AdsSyncWriteReq(    AmsAddr*    pServerAddr,    // Ams address of ADS server
                             unsigned long    indexGroup,        //    index group in ADS server interface
                             unsigned long    indexOffset,    // index offset in ADS server interface
                             unsigned long    length,            // count of bytes to write
                             void*                pData                // pointer to the client buffer
                            );

__declspec( dllexport )
long __stdcall AdsSyncReadReq( AmsAddr*    pAddr,                        // Ams address of ADS server          
                             unsigned long        indexGroup,        //    index group in ADS server interface
                             unsigned long        indexOffset,    // index offset in ADS server interface
                             unsigned long        length,            // count of bytes to read
                             void*                pData                // pointer to the client buffer
                            );

先启动TwinCAT XAE(VS 2010)也就是VS 2010,新建一个TwinCAT的Project。在SYSTEM里的License选项里可以点击“Activate 7 Days Trial License”,然后会出现以下的对话框,填入生成的Code就完成了注册,用于开发,我们可以一直“Activate 7 Days Trial License”并可以使用TwinCAT 3的完整功能。

enter security code

如果我们使用了Beckhoff的EtherCAT的IO模块,并通过Ethernet线和PC相连,我们可以将这个设备和TwinCAT相连,在Solution Explorer里的I/O一栏里,展开它,点击Devices,点鼠标右键,点选Scan就可以连接我们的EtherCAT I/O模块了,如下图所示,也可使用工具栏上的Scan图标。

scan_devices

如果发现有正确连接,就会出现下图的对话框。

IO devices found

点选OK,我们就是Active Free Run了。然后在Solution Explorer会看到Device的信息,如下图所示。

device ethercat

如果我们点选譬如Term 2 (EL2004),并展开它,就会看到这个模块的Channel,如果点击其中一个Channel就会看到上面的I/O,点击这个I/O就会在Variable这个Tab里找到ADS info,如下图所示。

ads infos

接下来我们就要使用这个ADS Info,并使用上面提到的API对其进行读和写。我们可以在以下链接中找到SAMPLE2(写)和SAMPLE3(读),这两个例程使用了SOFT PLC,提供的PLC可以加载到TwinCAT Project里,这里我们不使用PLC而是直接使用我们上面已经连接好的I/O模块:

http://download.beckhoff.com/download/Software/TwinCAT/TwinCAT3/Samples/TC1000-ADS/ADS/C/

#include <iostream>
#include <windows.h>
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h"

using namespace std;
void main()
{
  long     nErr, nPort;
  AmsAddr  Addr;
  PAmsAddr pAddr = &Addr;
  DWORD    dwData;

  // Open communication port on the ADS router
  nPort = AdsPortOpen();
  nErr = AdsGetLocalAddress(pAddr);
  if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';
  pAddr->port = 11;

  // Read the vlaue of the user, who has to be written to the PLC
  cout << "Value: ";
  cin >> dwData;

  //Port: 11, IGrp: 0x3040010, IOffs: 0xC10000D1, Len: 1
  nErr = AdsSyncWriteReq( pAddr, 0x3040010, 0xC10000D1, 0x1, &dwData );
  if (nErr) cerr << "Error: AdsSyncWriteReq: " << nErr << '\n';

  // Close the communication port
  nErr = AdsPortClose();
  if (nErr) cerr << "Error: AdsPortClose: " << nErr << '\n';
}

例程中的代码只需进行两处的改动(红笔处),就可以将我们输入的Data通过ADS接口传递给我们的EtherCAT I/O模块,这里使用的port of ADS server,index group in ADS server interface,index offset in ADS server interface,count of bytes to write,就是我们在上图看到的我们读到的ADS info。对于Read的例程SAMPLE3我就不多加描述了,就是使用AdsSyncReadReq这个API,然后给其相对应的ADS info就行。

2013年11月1日星期五

ASP.NET MVC 4使用技巧9:使用Google Charts和JSON

Google Charts 令人爱不释手,功能强大而且简单美观,文档非常完善。

https://developers.google.com/chart/

这里同时推荐一下Playerground,真是是一个非常好用的“工具”,可以非常方便地进行测试。

http://code.google.com/apis/ajax/playground/

如果想画一个line chart,并使用JSON得到做图的数据,很简单,以下就是一个简单的例子,在我们的.cshtml中添加上我们需要的js代码,在这个例子中,

  • 引用jsapi库并使用一系列Google Chart API,进行做图。
  • 通过点击一个button激活做图function。
  • 通过google.visualization.events.addListener得到点击line的事件。
  • 通过$.post('/YourController/GetDrawJsonData', {}, function (d) { … …); }); 从我们的Controller中得到Json数据。
<script type="text/javascript" src="//www.google.com/jsapi"></script>



    <script type="text/javascript">






        google.load("visualization", "1", { packages: ["corechart"] });



        google.setOnLoadCallback(drawChart);



        function drawChart() {



            var chart = new google.visualization.LineChart(document.getElementById('chart_div'));






            var button_show_all = document.getElementById('show_all');



            //-- Set a button onclick event



            // Multi graph.



            button_show_all.onclick = function () {



                var options =



                {



                    title: 'All Heuristic Methods',



                    colors: ['#E6E6E6'],



                    //colors: ['#93ACE7'],



                    legend: { position: 'none' }



                    //legend: { position: 'top', maxLines: '5' }



                    //series: [{ color: 'blue', visibleInLegend: true }, { color: 'blue', visibleInLegend: true }]



                };






                // Add our selection handler.



                google.visualization.events.addListener(chart, 'select', lineChartHandler);



                //-- Chart click event



                function lineChartHandler() {



                    var selection = chart.getSelection();



                    if (selection.length > 0) {



                        alert('A Line was selected');



                    }



                }






                $.post('/Plan/GetDrawJsonData', {},



                function (d) {



                    //alert(d);



                    var data = google.visualization.arrayToDataTable(d);



                    // At the end draw the chart.



                    chart.draw(data, options);



                });



            }



   }






</script>








它的html代码就更简单了:



<input id="show_all" type="button" class="btn btn-info" value="Show All Charts"  />



<br />



<div id="chart_div" style="width: auto; height: 400px;">



</div>





在Controller中只需要加入生成JSON数据的方法:



public ActionResult GetDrawJsonData()



{



     List<object> data_todraw = ... ... ...;



    return Json(data_todraw);



}


 


进阶一下,如果想要通过JSON改变做图的options,譬如说是颜色,其实也很方便,先在js中加入一个chart_opt的arrary:



var chart_opt = new Object();



chart_opt.title = "Heuristic Method";



var colors = new Array();



colors[0] = "#93ACE7"



chart_opt.colors = colors;



var lengend = new Object();



lengend.position = 'none';



chart_opt.legend = lengend;


 


然后通过一个function得到json数据,这里的row: input_counter是一个输入,我们的Controller的方法可以通过这样的方式得到这个输入:



$.post('/YourController/GetDrawJsonOptionSingle', { row: input_counter },



function (f) {



   //console.log(f);



   //If for some reason you cannot modify your server side script to provide 



   //a valid JSON in the tags property you could still use eval instead of $.parseJSON:var tags = $.parseJSON(response.tags);



   var colors_tmp = eval(f);



   console.log(colors_tmp);



   for (i = 0; i < colors_tmp.colors.length; i++) {



       colors[i] = colors_tmp.colors[i];



   }



});


与之对应的Controller里的method,需要使用一个Class里面定义colors的List,最后通过return Json(…)返回JSON数据:



public class ChartOptions
{
    public List<string> colors;
}


 

public ActionResult GetDrawJsonOptionSingle(int row)
{

 

    ChartOptions tmp = new ChartOptions();



    tmp.colors = new List<string>();



    for (int i = 0; i < ROW_COUNT_ALL; i++)



    {



        if (i == row)



        {



            tmp.colors.Add("#F30A0A");



        }



        else



        {



            tmp.colors.Add("#E6E6E6");



        }



    }



    return Json(tmp);



}

2013年8月13日星期二

ASP.NET MVC 4使用技巧8:自定义CheckBox及ActionResult的Subtypes

今天简单介绍一下如何编写一个自定义的CheckBox:

<script type="text/javascript">
    function unhide(id_name, check_box) {
        var check = (check_box.checked) ? "block" : "none";
        document.getElementById(id_name).style.display = check;
    }
</script>



@Html.CheckBoxFor(model => model.NotifyEmail, new { @checked = "unchecked" , @onclick="unhide('hidden-input-email', this)"})Email Notification<br>
<div id="hidden-input-email" style="display:none">
<p>
   @Html.LabelFor(model => model.Email) 
   @Html.TextBoxFor(model => model.Email, new { @readonly="readonly" })
</p>
<div class="editor-field">
   @Html.TextAreaFor(model => model.EmailInfos, new { style = "width: 200px; height: 100px;" })
</div>


       
上面的View代码,使用了自定义的CheckBox
简单的说明一下:

  1. @Html.CheckBoxFor(model => model.NotifyEmail, new { @checked = "unchecked" , @onclick="unhide('hidden-input-email', this)"})Email Notification<br>
  2. 当我们点击这个CheckBox的时候会将隐藏的输入框显示出来,这里使用了一个简单的Javascript,当@onclick的事件被触发时。
  3. 同时这里使用@checked = "unchecked"设置初始为unchecked。
  4. 参数:model => model.NotifyEmail是我们对于checkbox的view model binding。
  5. 我们的TextAreaFor也通过参数:new { style = "width: 200px; height: 100px;" }自定义了大小。

 

ActionResult有很多种Subtypes,我今天才知道,以前只用过3种。
出处:http://forums.asp.net/t/1448398.aspx


       
ViewResult - Renders a specifed view to the response stream

PartialViewResult - Renders a specifed partial view to the response stream

EmptyResult - An empty response is returned

RedirectResult - Performs an HTTP redirection to a specifed URL

RedirectToRouteResult - Performs an HTTP redirection to a URL that is determined by the routing engine, based on given route data

JsonResult - Serializes a given ViewData object to JSON format

JavaScriptResult - Returns a piece of JavaScript code that can be executed on the client

ContentResult - Writes content to the response stream without requiring a view

FileContentResult - Returns a file to the client

FileStreamResult - Returns a file to the client, which is provided by a Stream

FilePathResult - Returns a file to the client