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.


  • Qt Champions 2016

    @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

    http://doc.qt.io/qt-5/qpainter.html



  • @mrjj

    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


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.