简易画图板的再次优化

前面我们实现了画板的一些功能,但是有没有注意到,每次窗口的改变,你绘制的图形就会不见了。

1、首先分析一下,为什么窗口一改变,绘制的图形就没了。这是因为窗体一旦发生改变,就会调用paint方法。

而paint方法,是系统自己有的,一般系统自己有的方法,都没有具体的实现,里面的内容为空,所以,一旦调用paint方法的时候,里面的内容为空,所以你开始绘制的图形都没了。要解决此问题,我们只需要重写paint方法就可以,首先看你的图形是在什么地方绘制的,是JFrame窗口还是JPanel里面。在什么里面绘图,paint方法就写在什么里面。

2、接下来就是paint方法里面的内容了

a.里面必须要利用super来调用父类的方法,这是因为默认的画板是由父类的画的,你重写的画板必须保持原来的状态。

super.paint(g);

b.重新绘制图形,首先是要保存,当绘制图形的时候我们利用坐标来绘制的。所以首先会想到可以通过数组来保存坐标,但是这样的话,数组的长度的定义会是一个问题。当数组长度为100时,它只能保存25条直线的坐标。所以要想另外的办法,我们可以定义一个图形数组,直接保存图形,也许长度问题还是没有解决,这样我们可以定义一个图形的自定义队列用来保存图形。

队列其实就是利用两个数组来实现的,先定义一个数组src,再定义一个比这长一个单位的数组dest。先把之前的数组src拷贝到新的数组dest中,再长一点的数组末尾加入形状。然后在交换两个数组src和dest,这样就形成了一个队列。主要代码如下:

Shape[] src = new Shape[0];

/**
* 添加元素方法
*/
public void add(Shape shape) {
//创建新数组
Shape[] dest = new Shape[src.length+1];
//拷贝
for(int i=0;i<src.length;i++){
dest[i] = src[i];
}
dest[src.length] = shape;
//交换
src = dest;
}

c.上面实现了图形的保存,但当使用的时候还需要一些其他的功能,比如队列的长度,指定位置的元素。这些功能都比较简单,就不再次贴代码了。

d.然后再重绘paint方法中得到数组,最后利用for循环,把之前绘制所有的图形都重新再绘制一遍,这样再去改变窗体时,调用的就是重新写的paint方法。绘制的图形就不会因为窗体的改变而消失。

注意:paint不能写成其他名字,要不然重绘功能还是不会实现,一定要写成paint

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!
以下是一个基于VC++ MFC的简易画图板代码示例: 首先,创建一个MFC应用程序,选择“单文档”类型,然后在资源编辑器中添加一个菜单项“画图板”。 在CMainFrame类中添加以下代码: ```cpp #include "MyView.h" class CMainFrame : public CFrameWnd { public: CMainFrame(); protected: afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct); afx_msg void OnPaint(); afx_msg void OnSize(UINT nType, int cx, int cy); afx_msg void OnDrawLine(); afx_msg void OnDrawRectangle(); afx_msg void OnDrawEllipse(); DECLARE_MESSAGE_MAP() private: MyView m_wndView; }; CMainFrame::CMainFrame() { Create(NULL, _T("Drawing Board"), WS_OVERLAPPEDWINDOW, CRect(0, 0, 800, 600)); } int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndView.Create(NULL, NULL, AFX_WS_DEFAULT_VIEW, CRect(0, 0, 0, 0), this, AFX_IDW_PANE_FIRST, NULL)) { TRACE0("Failed to create view window\n"); return -1; } return 0; } void CMainFrame::OnPaint() { CPaintDC dc(this); // device context for painting CRect rect; GetClientRect(&rect); dc.FillSolidRect(&rect, RGB(255, 255, 255)); } void CMainFrame::OnSize(UINT nType, int cx, int cy) { CFrameWnd::OnSize(nType, cx, cy); if (m_wndView.GetSafeHwnd()) m_wndView.MoveWindow(0, 0, cx, cy); } void CMainFrame::OnDrawLine() { m_wndView.SetDrawType(DRAW_LINE); } void CMainFrame::OnDrawRectangle() { m_wndView.SetDrawType(DRAW_RECTANGLE); } void CMainFrame::OnDrawEllipse() { m_wndView.SetDrawType(DRAW_ELLIPSE); } BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ON_WM_CREATE() ON_WM_PAINT() ON_WM_SIZE() ON_COMMAND(ID_DRAW_LINE, &CMainFrame::OnDrawLine) ON_COMMAND(ID_DRAW_RECTANGLE, &CMainFrame::OnDrawRectangle) ON_COMMAND(ID_DRAW_ELLIPSE, &CMainFrame::OnDrawEllipse) END_MESSAGE_MAP() ``` 在MyView类中添加以下代码: ```cpp enum DRAW_TYPE { DRAW_NONE = 0, DRAW_LINE, DRAW_RECTANGLE, DRAW_ELLIPSE }; class MyView : public CView { protected: MyView(); DECLARE_DYNCREATE(MyView) public: virtual void OnDraw(CDC* pDC); virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual ~MyView(); void SetDrawType(DRAW_TYPE type) { m_nDrawType = type; } protected: afx_msg void OnLButtonDown(UINT nFlags, CPoint point); afx_msg void OnMouseMove(UINT nFlags, CPoint point); afx_msg void OnLButtonUp(UINT nFlags, CPoint point); DECLARE_MESSAGE_MAP() private: DRAW_TYPE m_nDrawType; CPoint m_ptStart; CPoint m_ptEnd; }; MyView::MyView() { m_nDrawType = DRAW_NONE; } MyView::~MyView() { } BOOL MyView::PreCreateWindow(CREATESTRUCT& cs) { return CView::PreCreateWindow(cs); } void MyView::OnDraw(CDC* pDC) { CDocument* pDoc = GetDocument(); // TODO: add draw code here } void MyView::OnLButtonDown(UINT nFlags, CPoint point) { m_ptStart = point; CView::OnLButtonDown(nFlags, point); } void MyView::OnMouseMove(UINT nFlags, CPoint point) { if (nFlags & MK_LBUTTON) { CDC* pDC = GetDC(); CPen pen; pen.CreatePen(PS_SOLID, 2, RGB(0, 0, 0)); pDC->SelectObject(&pen); pDC->SetROP2(R2_NOTXORPEN); switch (m_nDrawType) { case DRAW_LINE: pDC->MoveTo(m_ptStart); pDC->LineTo(m_ptEnd); m_ptEnd = point; pDC->MoveTo(m_ptStart); pDC->LineTo(m_ptEnd); break; case DRAW_RECTANGLE: pDC->Rectangle(m_ptStart.x, m_ptStart.y, m_ptEnd.x, m_ptEnd.y); m_ptEnd = point; pDC->Rectangle(m_ptStart.x, m_ptStart.y, m_ptEnd.x, m_ptEnd.y); break; case DRAW_ELLIPSE: pDC->Ellipse(m_ptStart.x, m_ptStart.y, m_ptEnd.x, m_ptEnd.y); m_ptEnd = point; pDC->Ellipse(m_ptStart.x, m_ptStart.y, m_ptEnd.x, m_ptEnd.y); break; default: break; } ReleaseDC(pDC); } CView::OnMouseMove(nFlags, point); } void MyView::OnLButtonUp(UINT nFlags, CPoint point) { m_ptEnd = point; CView::OnLButtonUp(nFlags, point); } BEGIN_MESSAGE_MAP(MyView, CView) ON_WM_LBUTTONDOWN() ON_WM_MOUSEMOVE() ON_WM_LBUTTONUP() END_MESSAGE_MAP() ``` 在资源编辑器中为菜单项添加ID_DRAW_LINE、ID_DRAW_RECTANGLE和ID_DRAW_ELLIPSE命令ID。 最后,在CWinApp类的InitInstance()函数中添加以下代码: ```cpp BOOL CMyApp::InitInstance() { CWinApp::InitInstance(); CMainFrame* pFrame = new CMainFrame; m_pMainWnd = pFrame; pFrame->LoadFrame(IDR_MAINFRAME, WS_OVERLAPPEDWINDOW | FWS_ADDTOTITLE, NULL, NULL); m_pMainWnd->ShowWindow(SW_SHOW); m_pMainWnd->UpdateWindow(); return TRUE; } ``` 现在,你就可以编译并运行这个简易画图板了,它可以画线、矩形和椭圆。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值