Derma SpawnIcon点击事件异常求助:仅最后一个SpawnIcon的DoClick函数生效
问题原因分析
你遇到的问题核心有两个:
- 全局变量滥用:你的代码里
Frame、sheet、panel1、DScrollPanel、DPanel这些变量都没有用local声明,属于全局变量。每次调用DrawCratePrimWeapon时,这些全局变量都会被新创建的控件覆盖,导致之前的控件引用丢失,甚至层级混乱。 - 重复创建滚动面板并覆盖:每次调用
DrawCratePrimWeapon都会在panel1里新建一个DScrollPanel并设置Dock(FILL),后面的滚动面板会完全覆盖前面的,导致只有最后一个滚动面板里的SpawnIcon能被点击到,前面的都被挡住了。
修复方案
下面是修改后的完整代码,我会标注关键修复点:
修改后的 cl_hud.lua
-- 提前声明需要跨函数访问的局部变量,避免全局覆盖 local Frame, sheet, panel1, scrollPanel function DrawCrateDERMA( textebat, mdl ) Frame = vgui.Create( "DFrame" ) Frame:SetTitle( "Оружейный ящик" ) Frame:SetSize( ScrW() * 800/1920, ScrH() * 600/1080 ) Frame:Center() Frame:SetDraggable( false ) Frame:ShowCloseButton( true ) Frame:MakePopup(true) Frame:SetBackgroundBlur(false) Frame.Paint = function( self, w, h ) draw.RoundedBox( 5, 0, 0, w, h, Color( 25, 25, 25, 200 ) ) end sheet = vgui.Create( "DPropertySheet", Frame ) sheet:Dock( FILL ) panel1 = vgui.Create( "DPanel", sheet ) panel1.Paint = function( self, w, h ) draw.RoundedBox( 100, 0, 0, 280, 120, Color( 0, 0, 0, 0) ) end sheet:AddSheet( "Основное оружие", panel1, "materials/gunsicon.png" ) sheet.Paint = function( self, w, h ) draw.RoundedBox( 5, 0, 0, w, h, Color( 50, 50, 50, 150 ) ) end -- 只创建一次滚动面板,放在panel1内部 scrollPanel = vgui.Create( "DScrollPanel", panel1 ) scrollPanel:Dock( FILL ) -- 添加自动布局面板,替代手动设置坐标,让图标排列更规整 local layout = vgui.Create( "DIconLayout", scrollPanel ) layout:Dock( FILL ) layout:SetSpaceX( 20 ) layout:SetSpaceY( 20 ) layout:SetPadding( 20 ) scrollPanel.layout = layout -- 把布局面板挂载到滚动面板上,方便后续调用 end function DrawCratePrimWeapon(textebat, mdl, functonclick) -- 从统一的布局面板创建武器容器,不再重复新建滚动面板 local DPanel = scrollPanel.layout:Add( "DPanel" ) DPanel:SetSize( ScrW() * 200/1920, ScrH() * 100/1080 ) DPanel:SetBackgroundColor(Color(25,25,25,155)) local ImgKnop = vgui.Create( "SpawnIcon", DPanel ) ImgKnop:SetPos( 0, 0 ) ImgKnop:SetSize( DPanel:GetWide(), DPanel:GetTall() - 25 ) -- 留出标签空间 ImgKnop:SetModel( mdl ) -- 支持传入自定义点击逻辑,没有则用默认打印 ImgKnop.DoClick = functonclick or function() print("Clicked on weapon: " .. textebat) end local text1 = vgui.Create("DLabel", DPanel) text1:SetPos(0, DPanel:GetTall() - 20) text1:SetText(textebat) text1:SizeToContents() text1:CenterHorizontal() -- 让武器名称居中显示 end
修改后的 cl_init.lua
include("shared.lua") function ENT:Draw() self:DrawModel() end net.Receive("poslat", function() DrawCrateDERMA("GAVNO","models/props_interiors/Furniture_Couch02a.mdl") -- 不再需要手动传坐标,布局面板会自动排列 DrawCratePrimWeapon("228/1337","models/props_c17/furnitureStove001a.mdl") DrawCratePrimWeapon("22345528/1337","models/props_c17/oildrum001.mdl") DrawCratePrimWeapon("22328/1337","models/props_c17/lampShade001a.mdl") end)
关键修复点说明
- 全局变量改为局部变量:用
local声明所有控件变量,彻底避免了每次调用函数时覆盖之前的控件引用问题。 - 单一滚动面板+自动布局:在
DrawCrateDERMA里只创建一个滚动面板,并添加DIconLayout自动管理武器图标位置,替代手动设置坐标的繁琐操作,同时解决了面板互相覆盖的问题。 - 控件层级梳理:所有武器面板都添加到同一个布局容器中,确保所有
SpawnIcon都能正常显示并响应点击。 - 保留自定义点击逻辑:保留了传入
functonclick参数的功能,你可以根据需求传入自定义的点击处理代码。
这样修改后,所有的SpawnIcon都会正常响应点击事件,布局也更规整,还支持滚动显示更多武器。
内容的提问来源于stack exchange,提问作者DeloreanZ
相关产品推荐
相关产品推荐

