在wxLua面板中如何获取指定点的RGB颜色?
在ZeroBrane Studio中用wxLua实现左键点击获取面板像素颜色
问题背景
环境:Windows 10 + ZeroBrane Studio 2.01(MobDebug 0.805)
需求:左键点击wxPanel面板时,获取点击位置的像素颜色。尝试调用wxClientDC:GetPixel()方法时触发错误,提示attempt to call method 'GetPixel' (a nil value)。
最小复现代码:
package.cpath = package.cpath..";./?.dll;./?.so;../lib/?.so;../lib/vc_dll/?.dll;../lib/bcc_dll/?.dll;../lib/mingw_dll/?.dll;" require("wx") frame = wx.wxFrame(wx.NULL, wx.wxID_ANY, "How to use GetPixel?", wx.wxDefaultPosition, wx.wxSize(450, 450), wx.wxDEFAULT_FRAME_STYLE) panel = wx.wxPanel(frame, wx.wxID_ANY) function OnLeftUp(event) local point = { x = event:GetX(), y = event:GetY() } local pdc = wx.wxClientDC(panel) -- local colour = pdc:GetPixel(point.x, point.y) -- 该行触发错误 pdc:DrawText("Left mouse button UP at x = " .. tostring(point.x) .. " y = " .. tostring(point.y), point.x, point.y) -- pdc:DrawText("Left mouse button UP at x = " .. tostring(point.x) .. " y = " .. tostring(point.y) .. " Red = " .. tostring(colour:GetRed()), point.x, point.y) -- 该行触发错误 pdc:delete() end panel:Connect(wx.wxEVT_LEFT_UP, OnLeftUp) local sizer = wx.wxBoxSizer(wx.wxVERTICAL) sizer:Add(panel, 1, wx.wxEXPAND) frame:SetSizer(sizer) frame:SetAutoLayout(true) wx.wxGetApp():MainLoop()
解决方法
wxLua中的wxClientDC没有直接提供GetPixel方法,需要通过内存DC和Bitmap来捕获面板画面,再读取像素颜色。修改后的代码如下:
package.cpath = package.cpath..";./?.dll;./?.so;../lib/?.so;../lib/vc_dll/?.dll;../lib/bcc_dll/?.dll;../lib/mingw_dll/?.dll;" require("wx") frame = wx.wxFrame(wx.NULL, wx.wxID_ANY, "Get Pixel Color Demo", wx.wxDefaultPosition, wx.wxSize(450, 450), wx.wxDEFAULT_FRAME_STYLE) panel = wx.wxPanel(frame, wx.wxID_ANY) function OnLeftUp(event) local point = { x = event:GetX(), y = event:GetY() } -- 创建与面板尺寸匹配的Bitmap local size = panel:GetClientSize() local bitmap = wx.wxBitmap(size:GetWidth(), size:GetHeight()) local memdc = wx.wxMemoryDC(bitmap) -- 刷新面板并将内容绘制到内存DC panel:Refresh(false) panel:Update() memdc:Blit(0, 0, size:GetWidth(), size:GetHeight(), wx.wxClientDC(panel), 0, 0) -- 读取指定坐标的像素颜色 local pixelData = wx.wxPixelData(bitmap) if pixelData:Ok() then local pixel = pixelData:GetPixel(point.x, point.y) local rgbText = string.format("点击位置: x=%d, y=%d | RGB=(%d,%d,%d)", point.x, point.y, pixel.Red, pixel.Green, pixel.Blue) local dc = wx.wxClientDC(panel) dc:DrawText(rgbText, point.x, point.y) dc:delete() end -- 释放资源 memdc:delete() bitmap:delete() end panel:Connect(wx.wxEVT_LEFT_UP, OnLeftUp) local sizer = wx.wxBoxSizer(wx.wxVERTICAL) sizer:Add(panel, 1, wx.wxEXPAND) frame:SetSizer(sizer) frame:SetAutoLayout(true) wx.wxGetApp():MainLoop()
核心说明
- 用
wxMemoryDC和wxBitmap捕获面板当前的渲染内容,这是因为wxClientDC仅用于绘制,不支持直接读取像素 wxPixelData是wxLua中访问Bitmap像素的专用类,通过GetPixel方法可获取指定坐标的RGB分量- 操作完成后务必释放DC和Bitmap对象,避免内存泄漏
内容的提问来源于stack exchange,提问作者Youra_P
相关产品推荐
相关产品推荐

