原创|使用教程|编辑:郝浩|2013-03-19 11:53:26.000|阅读 1422 次
概述:本示例演示如何用Web图表控件ChartDirector绘制一个配置有刷新率的实时图表。在本例中,由一个计时器驱动的随机数生成器生成新的数据值,新产生的值会转换到数据数组中,然后显示在图表上。
# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>
相关链接:
本示例演示如何用Web图表控件 ChartDirector 绘制一个配置有刷新率的实时图表。在本例中,由一个计时器驱动的随机数生成器生成新的数据值,新产生的值会转换到数据数组中,然后显示在图表上。图表由一个秒表进行更新,这样图表的刷新率可独立于数据率。此外,这个图表支持暂停以方便用户查看,但是后台的数据仍然在继续更新。
图表刷新计时器调用CChartViewer.updateViewPort以触发CVN_ViewPortChanged消息,然后图表就会更新它的处理程序。下面提供了ChartDirector绘制实时图表的示例代码(PS:这个图表只适用于Windows)。
// realtimedemoDlg.cpp : implementation file // #include "stdafx.h" #include "realtimedemo.h" #include "realtimedemoDlg.h" #include <math.h> #ifdef _DEBUG #define new DEBUG_NEW #endif ///////////////////////////////////////////////////////////////////////////// // CRealtimedemoDlg dialog static const int DataRateTimer = 1; static const int ChartUpdateTimer = 2; static const int DataInterval = 250; // // Constructor // CRealtimedemoDlg::CRealtimedemoDlg(CWnd* pParent /*=NULL*/) : CDialog(CRealtimedemoDlg::IDD, pParent) { m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME); } void CRealtimedemoDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CRealtimedemoDlg) DDX_Control(pDX, IDC_GammaValue, m_ValueC); DDX_Control(pDX, IDC_BetaValue, m_ValueB); DDX_Control(pDX, IDC_AlphaValue, m_ValueA); DDX_Control(pDX, IDC_ChartViewer, m_ChartViewer); DDX_Control(pDX, IDC_RunPB, m_RunPB); DDX_Control(pDX, IDC_UpdatePeriod, m_UpdatePeriod); //}}AFX_DATA_MAP } BEGIN_MESSAGE_MAP(CRealtimedemoDlg, CDialog) //{{AFX_MSG_MAP(CRealtimedemoDlg) ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_TIMER() ON_WM_DESTROY() ON_BN_CLICKED(IDC_RunPB, OnRunPB) ON_BN_CLICKED(IDC_FreezePB, OnFreezePB) ON_CBN_SELCHANGE(IDC_UpdatePeriod, OnSelchangeUpdatePeriod) ON_CONTROL(CVN_ViewPortChanged, IDC_ChartViewer, OnViewPortChanged) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CRealtimedemoDlg message handlers // // Initialization // BOOL CRealtimedemoDlg::OnInitDialog() { CDialog::OnInitDialog(); // *** code automatically generated by VC++ MFC AppWizard *** // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // // Initialize member variables // m_extBgColor = getDefaultBgColor(); // Default background color // Clear data arrays to Chart::NoValue for (int i = 0; i < sampleSize; ++i) m_timeStamps[i] = m_dataSeriesA[i] = m_dataSeriesB[i] = m_dataSeriesC[i] = Chart::NoValue; // Set m_nextDataTime to the current time. It is used by the real time random number // generator so it knows what timestamp should be used for the next data point. SYSTEMTIME st; GetLocalTime(&st); m_nextDataTime = Chart::chartTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond) + st.wMilliseconds / 1000.0; // // Initialize controls // // Set up the data acquisition mechanism. In this demo, we just use a timer to get a // sample every 250ms. SetTimer(DataRateTimer, DataInterval, 0); // The chart update rate (in ms) m_UpdatePeriod.SelectString(0, _T("1000")); // Load icons for the Run/Freeze buttons loadButtonIcon(IDC_RunPB, IDI_RunPB, 100, 20); loadButtonIcon(IDC_FreezePB, IDI_FreezePB, 100, 20); // Initially set the Run mode m_RunPB.SetCheck(1); OnRunPB(); return TRUE; } // *** code automatically generated by VC++ MFC AppWizard *** // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CRealtimedemoDlg::OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect(&rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog::OnPaint(); } } // *** code automatically generated by VC++ MFC AppWizard *** // The system calls this to obtain the cursor to display while the user drags // the minimized window. HCURSOR CRealtimedemoDlg::OnQueryDragIcon() { return (HCURSOR) m_hIcon; } // // User clicks on the Run pushbutton // void CRealtimedemoDlg::OnRunPB() { // Enable chart update timer CString s; m_UpdatePeriod.GetLBText(m_UpdatePeriod.GetCurSel(), s); SetTimer(ChartUpdateTimer, _tcstol(s, 0, 0), 0); } // // User clicks on the Freeze pushbutton // void CRealtimedemoDlg::OnFreezePB() { // Disable chart update timer KillTimer(ChartUpdateTimer); } // // Handles timer events // void CRealtimedemoDlg::OnTimer(UINT_PTR nIDEvent) { switch (nIDEvent) { case DataRateTimer: // Is data acquisition timer - get a new data sample getData(); break; case ChartUpdateTimer: // Is chart update timer - request chart update m_ChartViewer.updateViewPort(true, false); break; } CDialog::OnTimer(nIDEvent); } // // View port changed event // void CRealtimedemoDlg::OnViewPortChanged() { drawChart(&m_ChartViewer); } // // User changes the chart update period // void CRealtimedemoDlg::OnSelchangeUpdatePeriod() { if (m_RunPB.GetCheck()) { // Call freeze then run to use the new chart update period OnFreezePB(); OnRunPB(); } } ///////////////////////////////////////////////////////////////////////////// // CRealtimedemoDlg methods // // A utility to shift a new data value into a data array // static void shiftData(double *data, int len, double newValue) { memmove(data, data + 1, sizeof(*data) * (len - 1)); data[len - 1] = newValue; } // // The data acquisition routine. In this demo, this is invoked every 250ms. // void CRealtimedemoDlg::getData() { // The current time in millisecond resolution SYSTEMTIME st; GetLocalTime(&st); double now = Chart::chartTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond) + st.wMilliseconds / 1000.0; // This is our formula for the random number generator do { // Get a data sample double p = m_nextDataTime * 4; double dataA = 20 + cos(p * 129241) * 10 + 1 / (cos(p) * cos(p) + 0.01); double dataB = 150 + 100 * sin(p / 27.7) * sin(p / 10.1); double dataC = 150 + 100 * cos(p / 6.7) * cos(p / 11.9); // Shift the values into the arrays shiftData(m_dataSeriesA, sampleSize, dataA); shiftData(m_dataSeriesB, sampleSize, dataB); shiftData(m_dataSeriesC, sampleSize, dataC); shiftData(m_timeStamps, sampleSize, m_nextDataTime); m_nextDataTime += DataInterval / 1000.0; } while (m_nextDataTime < now); // // We provide some visual feedback to the latest numbers generated, so you can see the // data being generated. // char buffer[1024]; sprintf(buffer, "%.2f", m_dataSeriesA[sampleSize - 1]); m_ValueA.SetWindowText(CString(buffer)); sprintf(buffer, "%.2f", m_dataSeriesB[sampleSize - 1]); m_ValueB.SetWindowText(CString(buffer)); sprintf(buffer, "%.2f", m_dataSeriesC[sampleSize - 1]); m_ValueC.SetWindowText(CString(buffer)); } // // Draw the chart and display it in the given viewer // void CRealtimedemoDlg::drawChart(CChartViewer *viewer) { // Create an XYChart object 600 x 270 pixels in size, with light grey (f4f4f4) // background, black (000000) border, 1 pixel raised effect, and with a rounded frame. XYChart *c = new XYChart(600, 270, 0xf4f4f4, 0x000000, 1); c->setRoundedFrame(m_extBgColor); // Set the plotarea at (55, 62) and of size 520 x 175 pixels. Use white (ffffff) // background. Enable both horizontal and vertical grids by setting their colors to // grey (cccccc). Set clipping mode to clip the data lines to the plot area. c->setPlotArea(55, 62, 520, 175, 0xffffff, -1, -1, 0xcccccc, 0xcccccc); c->setClipping(); // Add a title to the chart using 15 pts Times New Roman Bold Italic font, with a light // grey (dddddd) background, black (000000) border, and a glass like raised effect. c->addTitle("Field Intensity at Observation Satellite", "timesbi.ttf", 15 )->setBackground(0xdddddd, 0x000000, Chart::glassEffect()); // Add a legend box at the top of the plot area with 9pts Arial Bold font. We set the // legend box to the same width as the plot area and use grid layout (as opposed to // flow or top/down layout). This distributes the 3 legend icons evenly on top of the // plot area. LegendBox *b = c->addLegend2(55, 33, 3, "arialbd.ttf", 9); b->setBackground(Chart::Transparent, Chart::Transparent); b->setWidth(520); // Configure the y-axis with a 10pts Arial Bold axis title c->yAxis()->setTitle("Intensity (V/m)", "arialbd.ttf", 10); // Configure the x-axis to auto-scale with at least 75 pixels between major tick and // 15 pixels between minor ticks. This shows more minor grid lines on the chart. c->xAxis()->setTickDensity(75, 15); // Set the axes width to 2 pixels c->xAxis()->setWidth(2); c->yAxis()->setWidth(2); // Now we add the data to the chart. double lastTime = m_timeStamps[sampleSize - 1]; if (lastTime != Chart::NoValue) { // Set up the x-axis to show the time range in the data buffer c->xAxis()->setDateScale(lastTime - DataInterval * sampleSize / 1000, lastTime); // Set the x-axis label format c->xAxis()->setLabelFormat("{value|hh:nn:ss}"); // Create a line layer to plot the lines LineLayer *layer = c->addLineLayer(); // The x-coordinates are the timeStamps. layer->setXData(DoubleArray(m_timeStamps, sampleSize)); // The 3 data series are used to draw 3 lines. Here we put the latest data values // as part of the data set name, so you can see them updated in the legend box. char buffer[1024]; sprintf(buffer, "Alpha: <*bgColor=FFCCCC*> %.2f ", m_dataSeriesA[sampleSize - 1]); layer->addDataSet(DoubleArray(m_dataSeriesA, sampleSize), 0xff0000, buffer); sprintf(buffer, "Beta: <*bgColor=CCFFCC*> %.2f ", m_dataSeriesB[sampleSize - 1]); layer->addDataSet(DoubleArray(m_dataSeriesB, sampleSize), 0x00cc00, buffer); sprintf(buffer, "Gamma: <*bgColor=CCCCFF*> %.2f ", m_dataSeriesC[sampleSize - 1]); layer->addDataSet(DoubleArray(m_dataSeriesC, sampleSize), 0x0000ff, buffer); } // Set the chart image to the WinChartViewer viewer->setChart(c); delete c; } ///////////////////////////////////////////////////////////////////////////// // General utilities // // Get the default background color // int CRealtimedemoDlg::getDefaultBgColor() { LOGBRUSH LogBrush; HBRUSH hBrush = (HBRUSH)SendMessage(WM_CTLCOLORDLG, (WPARAM)CClientDC(this).m_hDC, (LPARAM)m_hWnd); ::GetObject(hBrush, sizeof(LOGBRUSH), &LogBrush); int ret = LogBrush.lbColor; return ((ret & 0xff) << 16) | (ret & 0xff00) | ((ret & 0xff0000) >> 16); } // // Load an icon resource into a button // void CRealtimedemoDlg::loadButtonIcon(int buttonId, int iconId, int width, int height) { GetDlgItem(buttonId)->SendMessage(BM_SETIMAGE, IMAGE_ICON, (LPARAM)::LoadImage( AfxGetResourceHandle(), MAKEINTRESOURCE(iconId), IMAGE_ICON, width, height, LR_DEFAULTCOLOR)); }
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@pclwef.cn
文章转载自:慧都控件