【记录】将QT上绘制的PRPD图谱转为vs+DUILIB绘制中遇到的问题

本文介绍了如何将使用Qt绘制的PRPD图谱转换为在Visual Studio+DUILIB框架下绘制。在Qt中,通过先绘制到位图再显示在窗口上确保图谱准确性。而在DUILIB中,直接绘制导致图谱数据重新分布,最终采用位图方式解决窗口缩放问题。文章强调了位图的使用、绘图函数的差异以及资源释放的重要性。
摘要由CSDN通过智能技术生成

这里写自定义目录标题

QT绘制PRPD

在Qt上先将图谱绘制到位图中,然后再将位图绘制到QWidget上,这样外部窗口变换大小都不会影响到图谱的准确性。

	m_Bitmap->fill(Qt::transparent);//用透明色填充
    QPainter m_MemDC(m_Bitmap);
    QPainter* m_MemDCBK=pDC;

    QRect rectBK = rect;
    m_MemDCBK->fillRect(rectBK,QColor(0,0,0));
    m_MemDCBK->setPen(QColor(255,255,255));
    QRect rectFP = QRect(0,0,FP_X,FP_Y);
    m_MemDC.fillRect(rectFP,m_colorBK);
    QPen GrayPen(m_colorBKLine,0,Qt::SolidLine);
    m_MemDC.setPen(GrayPen);
	m_MemDC.drawLine(rectFP.left(),rectFP.top()+rectFP.height()/2,rectFP.right(),rectFP.top()+rectFP.height()/2);
    int nOldY = rectFP.top()+rectFP.height()/2;
    int nY = rectFP.top()+rectFP.height()/2;
    for(int k=rectFP.left();k<rectFP.right();k++)//画背景正弦曲线
    {
        nY = rectFP.top()+rectFP.height()/2-sin((double)(k-rectFP.left())/(double)(rectFP.width()/2)*PI)*(rectFP.top()+rectFP.height()/2);
        m_MemDC.drawLine(k-1,nOldY,k,nY);
        nOldY=nY;
    }
    int nTypeValue ;
    if(g_nFPType == 0)
    {
        nTypeValue = FP_Y/2;
    }
    else if(g_nFPType == 1)
    {
        nTypeValue = FP_Y;
    }

    for(int i=0;i<FP_X;i++)
    {
        int move_num=i-g_nRotate[chan_idx_]*FP_X/360;
        if(move_num<=0)
        {
            move_num=move_num+FP_X;
        }
        int phase_move_num;  //定义旋转多少相位
        phase_move_num=move_num%FP_X;
        for(int j=0;j<FP_Y;j++)
        {
            if(abs(j-nTypeValue)>m_nBK)
            {
                if(m_colorBK!=GetFPColor(m_sStateMap[i][j]))
                {
                    m_MemDC.setPen(GetFPColor(m_sStateMap[i][j]));
                    m_MemDC.drawPoint(QPointF(i,j));
                }
            }
        }
    }
    m_MemDCBK->setFont(QFont("Times",8,QFont::Black));
    m_MemDCBK->drawPixmap(30,0,rect.width()-30,rect.height()-20,*m_Bitmap,0,0,FP_X,FP_Y);

    m_MemDC.end();
    m_MemDCBK->end();

图谱转为vs+DUILIB绘制

刚将代码放到duilib框架中时,想的是直接绘制出来

void xxx::PaintBkImage(HDC hDC)
{
	int32_t left = m_rcItem.left;
	int32_t right = m_rcItem.right - 1;
	int32_t top = m_rcItem.top;
	int32_t bottom = m_rcItem.bottom - 1;
	int32_t width = right - left;
	int32_t height = bottom - top;
	RECT rc_line = { 0 };
	
		rc_line.left = 0;
		rc_line.top = height / 2;
		rc_line.right = width;
		rc_line.bottom = height / 2;
		CRenderEngine::DrawLine(memdc, rc_line, 2, m_colorBKLine);

		int nOldY = height / 2;
		int nY = height / 2;

		for (int k = 0; k<width; k++)//画背景正弦曲线
		{
			nY = top + height / 2 - sin((double)(k - left) / (double)(width/ 2)*PI)*(top + height / 2);
			rc_line.left = k - 1;
			rc_line.top = nOldY;
			rc_line.right = k;
			rc_line.bottom = nY;
			CRenderEngine::DrawLine(memdc, rc_line, 3, m_colorBKLine);
			nOldY = nY;
		}
		PaintWaves(hDC);
}
void xxx::PaintWaves(HDC hDC)
{
		int nTypeValue;
		if (g_nFPType == 0)
		{
			nTypeValue = FP_Y / 2;
		}
		else if (g_nFPType == 1)
		{
			nTypeValue = FP_Y;
		}
		for (int i = 0; i<FP_X; i++)
		{
	        int move_num=i-g_nRotate[chan_idx_]*FP_X/360;
	        if(move_num<=0)
	        {
	            move_num=move_num+FP_X;
	        }
	        int phase_move_num;  //定义旋转多少相位
	        phase_move_num=move_num%FP_X;
			for (int j = 0; j<FP_Y; j++)
			{
				if (abs(j - nTypeValue)>m_nBK)
				{
					if (m_colorBK != GetFPColor(m_sStateMap[i][j]))
					{
						HPEN pen = CreatePen(PS_SOLID, 2, GetFPColor(m_sStateMap[i][j]));
						HGDIOBJ old_pen = SelectObject(hDC, pen);
						Ellipse(hDC, i, j, i + 1, j + 1);
						SelectObject(hDC, old_pen);
						DeletePen(pen);
					}
				}
			}
		}
}

这样就遇到了一个很严重的问题,背景正弦曲线虽然会跟着窗口大小变动而变动,但图谱的数据却重新分布重新绘制了。所以还是得使用位图来绘制。

void xxx::PaintBkImage(HDC hDC)
{
	HDC memdc = CreateCompatibleDC(hDC); 
	HBITMAP hbmp = CreateCompatibleBitmap(hDC, FP_X, FP_Y);
	HBITMAP holdbmp = (HBITMAP)SelectObject(memdc, hbmp);
		rc_line.left = 0;
		rc_line.top = FP_Y / 2;
		rc_line.right = FP_X;
		rc_line.bottom = FP_Y / 2;
		CRenderEngine::DrawLine(memdc, rc_line, 2, m_colorBKLine);

		int nOldY = FP_Y / 2;
		int nY = FP_Y / 2;

		for (int k = 0; k<FP_X; k++)//画背景正弦曲线
		{
			nY = FP_Y / 2 - sin((double)(k - left) / (double)(FP_X / 2)*PI)*(FP_Y / 2);
			rc_line.left = k - 1;
			rc_line.top = nOldY;
			rc_line.right = k;
			rc_line.bottom = nY;
			CRenderEngine::DrawLine(memdc, rc_line, 3, m_colorBKLine);
			nOldY = nY;
		}
		PaintWaves(hDC, memdc);
		StretchBlt(hDC, left, top, width, height, memdc, 0, 0, FP_X, FP_Y, SRCCOPY);
		
	SelectObject(memdc, holdbmp);
	DeleteDC(memdc);
}
void xxx::PaintWaves(HDC hDC, HDC memdc)
{
		int nTypeValue;
		if (g_nFPType == 0)
		{
			nTypeValue = FP_Y / 2;
		}
		else if (g_nFPType == 1)
		{
			nTypeValue = FP_Y;
		}
		for (int i = 0; i<FP_X; i++)
		{
	        int move_num=i-g_nRotate[chan_idx_]*FP_X/360;
	        if(move_num<=0)
	        {
	            move_num=move_num+FP_X;
	        }
	        int phase_move_num;  //定义旋转多少相位
	        phase_move_num=move_num%FP_X;
			for (int j = 0; j<FP_Y; j++)
			{
				if (abs(j - nTypeValue)>m_nBK)
				{
					if (m_colorBK != GetFPColor(m_sStateMap[i][j]))
					{
						HPEN pen = CreatePen(PS_SOLID, 2, GetFPColor(m_sStateMap[i][j]));
						HGDIOBJ old_pen = SelectObject(memdc, pen);
						Ellipse(memdc, i, j, i + 1, j + 1);
						SelectObject(memdc, old_pen);
						DeletePen(pen);
					}
				}
			}
		}
}

总结

Qt画点使用drawPoint,用dui画点要用Ellipse,且right - left = bottom - top。
创建新的HBITMAP要使用CreateCompatibleBitmap而不能用CreateBitmap,原因是CreateBitmap似乎只支持8x8的位图。
画笔、画刷、画布、位图的句柄用完之后一定要释放。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值