当前位置: 首页 > news >正文

在CodeBolcks下wxSmith的C++编程教程——使用自定义绘制和鼠标处理创建项目

0.前言

 欢迎来到 wxSmith 教程页面!wxSmith 与 Code::Blocks、wxWidgets 和 C++ 编译器相结合,为您提供一种所见即所得的方式来创建具有图形用户界面 (GUI) 的应用程序。该组合形成了一个用于快速应用程序开发 (RAD) 的工具,可在 Linux、Mac OS X 和 Windows 上运行。当您工作时,您会在屏幕上看到您正在设计的表单;他们看着你,就像他们看着你的程序的用户一样。

这些教程假设您是Code::Blocks 或 wxWidgets 的初学者,事实上,它们也是学习它们的好教程;假设您对 C++ 有基本的了解,您能够看懂教程中的C++实例代码。
这套教程的其他文章可以从以下文章中找到:

在CodeBolcks下wxSmith的C++编程教程——wxSmith教程目录(序言) - lexyao - 博客园

编写这篇文章参照了Code::Blocks 用户文档中wxSmith教程的以下文章:

WxSmith tutorial: Creating items with custom paint and mouse handling - Code::Blocks

在这篇文章中你将看到以下内容:

  1. 使用自定义绘制程序创建项目
  2. 创建简单资源并覆盖绘制方法
  3. 使用鼠标取点绘制曲线
  4. 绘制图形常用的函数
  5. 结束语

1.使用自定义绘制程序创建项目

从Code::Blocks 用户文档中wxSmith教程(原英文版教程)中表达的意思来看,原作者是想编写一个绘制图形的教程,其中也包括使用鼠标事件。可惜的是原作者只写了一个开头,写出完整的教程。
按着这篇教程的立意,要写的内容也是非常有用的,所以我决定根据我的一些猜想写出教程后续的内容 —— 当然,只是从使用的角度出发确定教程的内容,不一定是原教程作者的本意。
我们已经在之前的教程中学习了使用 wxSmith 的好技巧,现在是时候做更好的了。通常在编写一些更高级的应用程序时,有时发现 wxWidgets 提供的组件不符合我们的目的,尤其是当我们需要以图形形式呈现一些数据时。希望与几乎所有 GUI 工具包一样,wxWidgets 也为此做好了准备,并使我们能够创建具有自定义绘图和鼠标处理的项目 —— 这允许我们创建任何我们喜欢的项目。

在我们开始创建自定义项目之前,需要一些背景知识。 您应该知道的第一件事是 wxWidgets 如何绘制项目。

大多数项目都有操作系统或系统中可用的其他工具包(如 gtk+)提供的自定义绘制程序。对于此类项目,当作系统发布重新绘制项目的请求时,此请求要么由 wxWidgets 将消息转发回系统,要么甚至在没有任何 wxWidgets 干预的情况下完成整个过程。不幸的是,这意味着我们无法替换大多数项目的绘制程序,即使它在某些平台上有效,但在其他平台上也无法使用。在 wxSmith 中可用的项目中,只有 wxPanel 可以保证使用自定义绘制程序。

现在,如果我们在 wxPanel 上覆盖绘画,wxWidgets 将在每个绘画请求上发布两个事件:

  • 擦除背景事件 (EVT_ERASE_BACKGROUND)
  • 绘制事件 (EVT_PAINT)

第一个用于在添加内容之前准备我们的项目所占用的区域,第二个用于进行实际绘图。我们不必覆盖这两个事件,因此我们可以只绘制自定义背景或仅绘制自定义内容,而将背景保留为默认背景。

在编写自定义绘制方法之前,您应该知道的第二件事是 wxWidgets 使用 wxDC 对象进行绘制。在擦除背景事件的情况下,此对象在事件中提供;对于 Paint 事件,我们必须手动创建此对象。要获取有关 wxDC 和绘图函数的更多信息,请查看 wxWidgets 文档中的此页面。这个页面中有wxWidgets 2.8.8中wxDC 的介绍,你也可以在往上获得其他版本的文档。

2.创建简单资源并覆盖绘制方法

像往常一样,我们将从一个空应用程序开始,项目名称为tu07。项目只有一个简单的窗口,出于我们的目的,我们需要在窗口中添加一个 wxPanel 作为我们绘制图形的场所。用鼠标调整wxPanel的大小,为我们绘制图形留出空间:

wechat_2025-09-25_145837_296

 

现在让我们转到属性浏览器中的事件选项卡。您可能会看到 wxPanel 可以处理比其他项目更多的事件。这是因为它可以用作自定义项的基础,这些项可能具有任何标准事件的自定义处理程序。好的,让我们找到EVT_PAINT方法(它应该在顶部)并添加一个新的空事件。

我们应该在处理程序中做的第一件事是创建我们将使用的 wxDC 对象。如果您查看 wxWidgets 文档,您可能会读到不这样做会导致 wxWidgets 进入无限循环,因为 paint 方法将被一遍又一遍地调用。

我们可以在这里使用几种类型的 wxDC 对象。最常用的是 wxPaintDC:

void tu07Frame::OnPanel1Paint(wxPaintEvent& event)
{wxPaintDC dc( Panel1 );
}

你可以看到我们传递了面板的指针作为参数 - wxPaintDC 需要一个指向我们将在其构造函数中绘制的项目的指针。请记住不要使用 this 指针。

现在让我们添加一些绘图代码 - 只是一些对角线来测试绘图是否有效:

void tu07Frame::OnPanel1Paint(wxPaintEvent& event)
{wxPaintDC dc( Panel1 );dc.DrawLine( 0, 0, 100, 100 );
}

DrawLine( 0, 0, 100, 100 )是最简单的绘图函数,它的意思是绘制一条从坐标(0,0),到(100,100)的直线。DrawLine函数的定义如下:

void DrawLine(wxCoord x1, wxCoord y1, wxCoord x2, wxCoord y2)

现在,我们构建并运行应用程序,窗口将如下所示:

wechat_2025-09-25_152035_624

看到这个画面,说明我们已经能够在面板上绘制图形了。为了更好地理解坐标的含义,我们可以尝试修改坐标值,多绘制几条直线,看是不是达到了我们预期的效果。比如我们把绘图直线的函数重复使用三次:

    dc.DrawLine(0, 0, 100, 100);dc.DrawLine(100,  100, 200, 0);dc.DrawLine(200, 0, 300, 100);

构建并运行应用程序,看增加的直线绘制的位置是不是我们预想的位置?

3.使用鼠标取点绘制曲线

鼠标是我们常用的取点工具,wxPanel有多个鼠标触发的事件。在这里我们将使用鼠标左键按下时鼠标的位置作为绘制直线的端点。为此我先准备几个变量和代码。
在tu07Main.app中添加以下代码:

 1 int nCount = 5, nPos = 0;
 2 wxPoint points[nCount];
 3 
 4 void tu07Frame::OnPanel1Paint(wxPaintEvent& event)
 5 {
 6     wxPaintDC dc(Panel1);
 7     dc.DrawLine(0, 0, 100, 100);
 8     dc.DrawLine(100,  100, 200, 0);
 9     dc.DrawLine(200, 0, 300, 100);
10     dc.DrawPolygon(nCount, points);
11 }

其中,dc.DrawPolygon绘制拟合曲线,nCount指定顶点的个数,points指定顶点的坐标。
构建并运行应用程序,虽然没有看到绘制的曲线,却也没有出现错误,这说明代码没有问题,只是还没有设置坐标数据。
怎么设置坐标数据呢?我是这样想的:

  • 在窗口中用鼠标点击,取得鼠标点击位置的坐标保存在变量points[nPos]中。
  • 得到一个点的坐标后将nPos+1,这样下一次就会设置另一个顶点,如此循环。

下面我们添加响应鼠标点击事件的代码:选择面板wxPanel,在属性浏览器中切换到事件页面,找到EVT_LEFT_DOWN事件,添加新的事件处理程序,并输入以下代码:

1 void tu07Frame::OnPanel1LeftDown(wxMouseEvent& event)
2 {
3     points[nPos] = event.GetPosition();
4     nPos++;
5     if(nPos >= nCount)nPos = 0;
6     Refresh();
7 }

上述代码中第3行取得鼠标点击时的坐标位置保存到变量points中;第4、5行指定下一个要修改的顶点;第6行刷新窗口让程序执行OnPanel1Paint把改变数据后的图形画出来。

wechat_2025-09-25_162259_934

 如果有兴趣,你也可以尝试添加一条语句,使用points[nPos]为圆心画一个小的圆圈用来标记下一个要改变位置的顶点。

4.绘制图形常用的函数

在程序中通过右键菜单查找函数DrawLine的定义可以找到dc.h文件中wxDC类的定义,从中可以看到可以使用的绘制图形以及与绘制图形有关的函数。

也可以打开以下网址查看其中关于wxDC成员函数的介绍:

wxDC

5.结束语

绘制图形是很有用的功能,在这一篇教程中讲述了绘制图形的基础知识,希望能起到抛砖引玉的效果。

http://www.hskmm.com/?act=detail&tid=17087

相关文章:

  • trae 配置mysql_mcp
  • Apache NiFi 1.28.1 集群 + Kerberos 认证 + 多租户模式部署
  • 基于Java+SpringBoot+SSM,Flask福聚苑社区团购体系(源码+LW+调试文档+讲解等)/福聚苑社区/团购系统/社区团购/福聚苑/团购/社区/环境/福聚苑小区/在线团购/社区购物
  • 按需引入echarts
  • 软件构造的用户交互设计 4章
  • 自定义制作docker容器自动自愈容器镜像
  • 如何利用海外 NetNut 网络代理与 AICoding 实战获取 iPhone 17 新品用户评论数据?
  • 第一次编码器测试
  • 04-FreeRTOS的概述及编程规范
  • 10_ select/poll/epoll实现服务端的io多路复用
  • 模拟实战配置实验
  • 国标GB28181公网直播EasyGBS如何构建全域覆盖的应急管理与安全生产解决方案?
  • Serilog.AspNetCore与Serilog的区别
  • 基于MATLAB S函数实现多智能体间歇通信仿真
  • 我天,前端岗要消亡了吗?
  • 闲话
  • java8的集合新API - --
  • 基于MATLAB/Simulink的500kW三相光伏逆变器仿真
  • Docker Compose启动多个镜像实例
  • 卫星时间同步平台:助力分布式测控系统同步工作
  • mkfx 对磁盘设置标签
  • C# Avalonia 15- Animation- Easing
  • 安卓编译重点记录
  • kubelet源码阅读(二)——device plugin 的ListAndWatch过程
  • CyberLink ColorDirector Ultra 2026 14.0.5712.0 视频后期调色
  • CF 1053 Div.2
  • vi编辑器
  • 豆油
  • MQTT
  • 源码安装fail2ban