java如何实现多线程绘图

java如何实现多线程绘图,第1张

首贺桐先,如果你只是要实现电子时钟,根本就不需要用到多线程

如果你真的是要使用,就新建一个类,实现Runnable接茄虚口就是了。

如:

class MyThread1 implements Runnable{

public MyThread(){

}

public void run(){

}

}

使用的时候,就:

Thread myThread=new Thread(new MyThread())

myThread.start()

如果要画图,你就直接把禅纳坦组件通过构造方法传到MyThread中就是了

我说说MFC的实现方法,下面的步骤是在VS2008英文版中实现的:

1、新建一个MFC Application,假设输入工程名称“test”

2、在第二步的“Application type”中选择“Dialog”,点击“finish”完成

3、打开“testDlg.cpp”文件,找到“CtestDlg::OnPaint()”函数

4、在“if else”结构的“else”中,那个系统自动生成的“CDialog::OnPaint()”函数前可以增加自己的绘图代码,如下

/////////////////////////////////////////////////////////////////

// 根据当前窗口大小创建一个DC(device context),就是一个画图的地方

CPaintDC dc(this)

// 保存绘图区大小的一个结构,他包括了窗口绘图区的长、宽

CRect rect

// 获取绘图区的大小

GetClientRect(&rect)

// 从坐标(100, rect.top)绘制直线到(100, rect.bottom)

dc.MoveTo(100, rect.top)

dc.LineTo(100, rect.bottom)

///////////////埋键//////////////////////////////////////////////////

5、如果真的需要新建一个线程来画直线的话可以这样:

(1)先写一个绘图的线程:

/////////////////////////////////////////////////////////////////

unsigned int _cdecl YourThread(void * pParam)

{

CtestDlg * pDlg = (CtestDlg *)pParam

CDC * pDC = pDlg->GetDC()

CRect rect

pDlg->GetClientRect(&rect)

pDC->MoveTo(100, rect.top)

pDC->LineTo(100, rect.bottom)

return 0

}

///////////////////////弯枝巧//////////////////////////////////////////

(2)在上面那个位置(if else结构的else里面)添加启动线程函数:

/////////////////////////////////////////////////////////////////

AfxBeginThread(YourThread, this)

/////////////////////////////////////////////////////////////////

这样就可以绘制一条黑色的直线了。

如果需要设置绘制线的颜色,在绘图前加上:

///////////////////////////////////////////////////////////////搭昌//

dc.SelectObject(&CPen(PS_SOLID, 1, RGB(255, 0, 0)))

/////////////////////////////////////////////////////////////////

意思是将线条设置为实线(PS_SOLID),线宽“1”,颜色红色

(RGB(255,0,0),红-绿-蓝的成分多少,范围0-255)

如果用DC的话,也就是设备内容(CreateCompatibleDC),多线程绘制意义不大。猛滑因为DC的缘故,线程必须要做同步,所以最终的效率不会有多大提升,也就是多一个系统调度时间片而已。

因此,

1、如果在CreateCompatibleDC的情况下必须使用多线程的话,那就是要用系统临界区对全局DC(绘图设备内容)做原子访问限制。具体可以搜索一下“系统临界区”。

2、如果不一定用何种绘图手段,需要多线程来大幅度提升效率的话,我推孝备荐采用定义全局画布缓冲区,然后对每一个绘图线程分配其各自的Rect,用以绘制,最后用DirectDraw或Direct3D将缓冲区复制到显卡即可。这样效率是最高的。

例如:

unsigned char g_ucGraphMemory[1024*768*4]//全局画布缓冲区,1024x768大小,32位色(A8R8G8B8)

typedef struct

{

unsigned char *ptrOffset

unsigned long dwLength

} DrawRect // 每个线程需要画的区域

int main()

{

/* 将整个画布(g_ucGraphMemory)分割成4块区域 */

DrawRect mRect[4]

mRect[0].ptrOffset = g_ucGraphMemory

mRect[1].ptrOffset = g_ucGraphMemory + (1024 * 768)

mRect[2].ptrOffset = g_ucGraphMemory + ((1024 * 768) * 2)

mRect[3].ptrOffset = g_ucGraphMemory + ((1024 * 768) * 3)

mRect[0].dwLength = 1024 * 768

mRect[1].dwLength = 1024 * 768

mRect[2].dwLength = 1024 * 768

mRect[3].dwLength = 1024 * 768

/***********************************************/

CreateThread(..., Thread1, &mRect[0]) // 创建绘图线程1

CreateThread(..., Thread2, &mRect[1]) // 创建绘图线程2

CreateThread(..., Thread3, &mRect[2]) // 创建绘图线程3

CreateThread(..., Thread4, &mRect[3]) // 创建绘图线程4

......

WaitForSingleObject() //巧知毁 等待线程绘图完毕

Direct3DCreate9()// 创建D3D设备

....

CreateTexture()// 创建纹理

....

CreateVertexBuffer()// 创建顶点缓冲区

....

LockRect()// 锁定纹理区域

memcpy()// 把g_ucGraphMemory复制到D3D纹理缓冲区内

....

DrawPrimitive()// 把纹理贴到多边形上

....

Present()// 显卡绘图

....

}

// 绘图线程1

DWORD WINAPI Thread1(DrawRect *ptrRect)

{

ptrRect->ptrOffset// 这个便是此线程需要绘制的区域始地址

ptrRect->dwLength // 这个是此线程需要绘制的区域大小

..... // 这里可以使用像素填充法、向量、GDI复制到内存区等手段进行绘制

..... // 通知主线程绘图完毕

}

// 绘图线程2

DWORD WINAPI Thread2(DrawRect *ptrRect)

{

....

}

// 绘图线程3

DWORD WINAPI Thread3(DrawRect *ptrRect)

{

....

}

// 绘图线程4

DWORD WINAPI Thread4(DrawRect *ptrRect)

{

....

}

以上只是一个多线程分块内存缓冲区绘图的流程例子,实际代码要多一些。此处主要表达分块的思想和主线程等待分线程绘图并进行显示的流程。

其中分块过程是为了简单,所以采用数组直接分段。实际中需要按照应用场合进行调整,如按行像素分块、按列像素分块、按矩形像素分块等。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/12355260.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-24
下一篇 2023-05-24

发表评论

登录后才能评论

评论列表(0条)

保存