# 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);
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;

}
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.

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;

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();
}
``````