• 使用 xlue 实现 tips


    经常遇到如下的需求

    鼠标hover到目标对象一定时间后,弹出tips或者窗口;

    鼠标离开目标对象一定时间后,隐藏tips或者窗口;

    鼠标从目标对象移动到弹出的窗口上,这种状况下不隐藏窗口;

    考虑到这种需求,绘制如下的状态图:

    未命名图片

    如上图所示,将tips的状态分为hide,showing,show,hiding,enter 五个状态;

    hide: tips没有显示

    showing: 准备显示tips

    show: 显示tips

    hiding: 准备隐藏tips

    enter: 鼠标进入了tips控件,这种状况下仍然显示 tips

    使用上面的状态图,清晰地描述了tips可能存在的各种状态,并确定了驱动事件有哪些。理清了思路。

    hide状态时:hover到目标控件会进入 showing 状态;

    showing 状态时:离开目标控件会返回到 hide 状态;

    进入 showing 状态后,开启一个timer,当timer结束后,如果仍然是 showing 状态,则转到 show 状态并显示tips

    show 状态时:离开目标控件会进入hiding状态;

    hiding 状态时:hover到目标控件会返回到 show 状态;

    进入 hiding 状态后,开启一个timer,当timer结束后,如果仍然是 hiding 状态,则转到 hide 状态并隐藏tips

    鼠标从目标控件移动到tips上,会使得状态从 show 转到 hiding 转到 enter, 此时tips仍然显示,当离开tips控件后,状态又转移回 hiding ,此时开启一个timer,timer结束后,同样根据是否仍然是 hiding 状态来隐藏tips

    编程实现:

    function AddWindowTip(tippedObj, text, callback)
    
        local function showTipsFunc(tippedObj, x, y)
            -- 创建tips窗口
            local hostwndId = "TipsHelper.TipsHostWnd.Instance." .. tippedObj:GetID()
            local objtreeId = "TipsHelper.TipsTree.Instance." .. tippedObj:GetID()
            local hostwndTemplateId = "TipsWndTemplate"
            local objtreeTemplateId = "TipsTreeTemplate"
    
            local hostwndManager = XLGetObject("Xunlei.UIEngine.HostWndManager")
            local hostwnd = hostwndManager:GetHostWnd(hostwndId)
            if hostwnd then
                local objtree = hostwnd:GetBindUIObjectTree()
                if objtree then
                    hostwnd:UnbindUIObjectTree()
                    local objtreeManager = XLGetObject("Xunlei.UIEngine.TreeManager")
                    objtreeManager:DestroyTree(objtree)
                end
                hostwndManager:RemoveHostWnd(hostwndId)
            end
            local templateManager = XLGetObject("Xunlei.UIEngine.TemplateManager")
            local wndTemplate = templateManager:GetTemplate(hostwndTemplateId, "HostWndTemplate")
            if not wndTemplate then
                return
            end
            local hostwnd = wndTemplate:CreateInstance(hostwndId)
            if not hostwnd then
                return
            end
            local objtreeTemplate = templateManager:GetTemplate(objtreeTemplateId, "ObjectTreeTemplate")
            local objtree = objtreeTemplate:CreateInstance(objtreeId)
            if not objtree then
                return
            end
            hostwnd:BindUIObjectTree(objtree)
            hostwnd:Create()
    
            -- 设定text
            local rootObj = objtree:GetRootObject()
            local textObj = objtree:GetUIObject("text")
            textObj:SetText(text)
            local width, height = textObj:GetTextExtent()
            textObj:SetObjPos(4,3,width,height)
            width,height = width + 8, height + 6
            rootObj:SetObjPos(0,0,width+8,height+6)
            
            -- 移动窗口位置
            local tippedOwner = tippedObj:GetOwner()
            local tippedHostWnd = tippedOwner:GetBindHostWnd()
            local l,t,r,b = tippedObj:GetObjPos()
            local left = l+(r-l-width)/2
            local top = b
            left,top = tippedHostWnd:HostWndPtToScreenPt(left,top)
            hostwnd:Move(left,top,width,height)
            
            return rootObj
        end
        local function hideTipsFunc(tippedObj)
            -- 销毁tips窗口
            local hostwndId = "TipsHelper.TipsHostWnd.Instance." .. tippedObj:GetID()
    
            local hostwndManager = XLGetObject("Xunlei.UIEngine.HostWndManager")
            local hostwnd = hostwndManager:GetHostWnd(hostwndId)
            if not hostwnd then
                return
            end
            
            local objtree = hostwnd:GetBindUIObjectTree()
            if objtree then
                hostwnd:UnbindUIObjectTree()
                local objtreeManager = XLGetObject("Xunlei.UIEngine.TreeManager")
                objtreeManager:DestroyTree(objtree)
            end
            hostwndManager:RemoveHostWnd(hostwndId)
            
            return true
        end
        
        -- state: tip 的状态, hide隐藏,showing正在显示,show显示,hiding正在隐藏,enter进入tips中
        local state = "hide"    -- 使用状态控制 tips 在各个状态间转换
        tippedObj:AttachListener("OnMouseMove", true, function(obj, x, y, flags)
            if state == "hide" then
                state = "showing"
                local timerMgr = XLGetObject("Xunlei.UIEngine.TimerManager")
                timerMgr:SetOnceTimer(function()
                    if state == "showing" then
                        local tipsObj = showTipsFunc(obj, x, y)
                        if tipsObj then
                            state = "show"
                            
                            --[[ 这段代码,使得移动到弹出的窗口上时,窗口不会被隐藏
                            tipsObj:AttachListener("OnMouseMove", true, function()
                                if state == "hiding" then
                                    state = "enter"
                                end
                            end)
                            tipsObj:AttachListener("OnMouseLeave", true, function()
                                if state == "enter" then
                                    state = "hiding"
                                    local timerMgr = XLGetObject("Xunlei.UIEngine.TimerManager")
                                    timerMgr:SetOnceTimer(function()
                                        if state == "hiding" then
                                            if hideTipsFunc(obj) then
                                                state = "hide"
                                                if callback and type(callback) == "function" then
                                                    callback(tippedObj, false)
                                                end
                                            end
                                        end
                                    end, 300)
                                end
                            end)
                            --]]
                            
                            if callback and type(callback) == "function" then
                                callback(obj, true)
                            end
                        end
                    end
                end, 300)
            elseif state == "hiding" then
                state = "show"
            end
        end)
        tippedObj:AttachListener("OnMouseLeave", true, function(obj, x, y, flags)
            if state == "show" then
                state = "hiding"
                local timerMgr = XLGetObject("Xunlei.UIEngine.TimerManager")
                timerMgr:SetOnceTimer(function()
                    if state == "hiding" then
                        if hideTipsFunc(obj) then
                            state = "hide"
                            if callback and type(callback) == "function" then
                                callback(tippedObj, false)
                            end
                        end
                    end
                end, 300)
            elseif state == "showing" then
                state = "hide"
            end
        end)
        
    end
  • 相关阅读:
    如何掌握所有的程序语言
    程序与证明
    卫星通信地面系统构成
    SCIP 环境搭建
    Homebrew install.sh
    macOS 内核之从 I/O Kit 电量管理开始
    matlab练习程序(空间椭圆拟合)
    多进程抢票加锁
    进程间数据传递
    队列用法
  • 原文地址:https://www.cnblogs.com/zuibunan/p/3915291.html
Copyright © 2020-2023  润新知