How to make a graph.
-
I have a function make a graph in MFC.
But I don't know how to convert MFC to Qt.This function is so simple.
Just draw the graph using CPaint.
but it receive the rect to draw using GetWindowRect and ScreenToClient.
and set CDC.I want to know about how to convert the above process.
void drawGraph() { CCPerfusionDemoDoc *pDoc = GetDocument(); if (pDoc->m_pVoxels == NULL || m_ComboSelMask.GetCurSel() == LB_ERR || m_bIsInit==false) return; float VoxelHUMax, VoxelHUMin, VoxelHURange; int VoxelHUMaxIndex; int w_headinterval = WIDTHINTERVAL + 50, w_backinterval = WIDTHINTERVAL, h_headinterval = HEIGHTINTERVAL + 20, h_backinterval = HEIGHTINTERVAL + 30; int n = pDoc->m_iFrameNumber - 1; VoxelHUMax = m_fVoxelHU[0]; VoxelHUMin = m_fVoxelHU[0]; VoxelHUMaxIndex = 0; for (int i = 0; i <= n; i++) { if (VoxelHUMax < m_fVoxelHU[i]) VoxelHUMax = m_fVoxelHU[i]; if (VoxelHUMin > m_fVoxelHU[i]) VoxelHUMin = m_fVoxelHU[i]; /////Max value if (m_fArteryAvgHU[VoxelHUMaxIndex] < m_fVoxelHU[i]) { VoxelHUMaxIndex = i; } } VoxelHURange = VoxelHUMax - VoxelHUMin; CRect rect; **m_StaticTempTDC.GetWindowRect(&rect); ScreenToClient(&rect);** int width = rect.Width(); int height = rect.Height(); width = width - w_backinterval - w_headinterval; **CDC* pDC = m_StaticTempTDC.GetDC();** double dt = pDoc->m_pVoxels[n]->m_fImageTime - pDoc->m_pVoxels[0]->m_fImageTime; double dRatioWidth = (double)(width) / dt; CPen VoxelPen(PS_SOLID, 1, RGB(0, 0, 255)); CPen VoxelDotPen(PS_DOT, 1, RGB(0, 0, 255)); CPen GridPen(PS_DOT, 1, RGB(0, 0, 0)); CPen *pOldPen = pDC->SelectObject(&VoxelPen); //// Grid double y; for (int i = 0; i <= 10; i++) { pDC->SelectObject(&GridPen); y = (double)(height - h_headinterval - h_backinterval) / 10 * i; pDC->MoveTo(w_headinterval, height - h_backinterval - y); pDC->LineTo(width + w_headinterval, height - h_backinterval - y); } double x1, x2, y1, y2; //y = (height / (Max - Min))*(Data - Min):크기비율 for (int i = 0; i < n; i++) { pDC->SelectObject(&VoxelPen); dt = pDoc->m_pVoxels[i]->m_fImageTime - pDoc->m_pVoxels[0]->m_fImageTime; x1 = dt * dRatioWidth + w_headinterval; dt = pDoc->m_pVoxels[i + 1]->m_fImageTime - pDoc->m_pVoxels[0]->m_fImageTime; x2 = dt * dRatioWidth + w_headinterval; y1 = (height - h_headinterval - h_backinterval) / VoxelHURange * (m_fVoxelHU[i] - VoxelHUMin ); y2 = (height - h_headinterval - h_backinterval) / VoxelHURange * (m_fVoxelHU[i + 1] - VoxelHUMin ); pDC->MoveTo(x1, height - h_backinterval - y1); pDC->LineTo(x2, height - h_backinterval - y2); } // grid y-axis for (int i = 0; i <= n; i++) { pDC->SelectObject(&VoxelDotPen); dt = pDoc->m_pVoxels[i]->m_fImageTime - pDoc->m_pVoxels[0]->m_fImageTime; pDC->MoveTo(dt * dRatioWidth + w_headinterval, height - h_backinterval); pDC->LineTo(dt * dRatioWidth + w_headinterval, height - h_backinterval - (((height - h_headinterval - h_backinterval) / VoxelHURange) * (m_fVoxelHU[i] - VoxelHUMin))); } // draw text CFont font; font.CreateFont(13, 0, 0, 0, FW_NORMAL, 0, 0, 0, 0, 0, 0, 0, 0, _T("Arial")); CFont* oldfont = pDC->SelectObject(&font); double VoxelInterval = VoxelHURange / 10; double Voxel = VoxelHUMax; for (int i = 0; i <= 10; i++) { CString scale; scale.Format("%0.3f", Voxel); Voxel -= VoxelInterval; pDC->TextOutA(10, h_headinterval + ((height - h_headinterval - h_backinterval) / 10)*i, scale); } for (int i = 0; i <= n;i++) { dt = pDoc->m_pVoxels[i]->m_fImageTime - pDoc->m_pVoxels[0]->m_fImageTime; x1 = dt * dRatioWidth; CString temp; temp.Format("%0.1f", dt); if (int(dt) / 10) pDC->TextOutA(x1 + w_headinterval - 12, height - h_backinterval + 10, temp); else pDC->TextOutA(x1 + w_headinterval - 9, height - h_backinterval + 10, temp); } pDC->SelectObject(oldfont); font.DeleteObject(); DeleteObject(&pOldPen); DeleteObject(VoxelPen); DeleteObject(GridPen); DeleteObject(VoxelDotPen); ReleaseDC(pDC);
-
I don't know whether this really answers your question but unlike you use the fancy new Qt stuff you can either use QCustomPlot or Qwt to render plots. There might be of course other solutions but these are the most commonly used ones.
-
@BREEZE_KO said:
pDC
well you need a widget and override its paintEvent
there you use QPainter which acts like the HDC.instead of
pDC->SelectObject(oldfont);
you use
thepainter.setFont
setPen
setBrush etc -
If I set up a mainWindow composed of layouts and I want to draw the line chart with QPainter in first layout,
how can I set up a place QPainter is drawing?simple source
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); QWidget* mainWidget = new QWidget(this); this->setCentralWidget(mainWidget); QGridLayout* mainLayout = new QGridLayout(); QGroupBox* gbox1 = new QGroupBox; QGroupBox* gbox2 = new QGroupBox; mainLayout->addWidget(gbox1); mainLayout->addWidget(gbox2); mainWidget->setLayout(mainLayout); //canvas QGridLayout* layout1 = new QGridLayout; ** QPainter paint(this); // ???**
-
@BREEZE_KO
As @mrjj suggested, I think you can just add a widget that you will use as your "canvas" to the layout and override it's paint event to draw what you want it to draw with a painter.void MyWidget::paintEvent(QPaintEvent *) { QPainter p; p.begin(this); p.drawLine(...); // drawing code p.end(); }
You can find plenty of docs and samples about this kind of thing.
you could start here : http://doc.qt.io/qt-5/qpainter.htm