永远的GitHub地址: https://github.com/JianBiHua/go_360_safe
如图效果(显示跟隐藏,都是慢慢显示的带尖角的窗体):
这里有几个小问题我还没有解决
- 动画时长设置太短(比如0.3秒),左右会多出一部分,
- 显示时,会闪现显示一个子控件,然后才正常动画
- ticker有时会崩溃.
显示: 当鼠标滑动到"简笔画/登陆/360图标"这块时
隐藏: 当鼠标厉害显示区域以及登陆框区域时。
# 实现原理说明
1. 如上节的波浪球绘制一样,得画一个带尖角的矩形。
2. 使用QT库自带的Mask功能(SetMask2)
核心代码如下:
A. 绘制代码:
- 我只画了尖角为上的情况,当然,也可以尖角为左为右。
- 为绘制了阴影
- 绘制的尖角矩形位置是动态的,效果才好看些
- 代码注释还算详细,自己理解吧。
func (p *PopupWidget) onPaint (event *gui.QPaintEvent) {
var device = p.BackingStore().PaintDevice()
var painter = gui.NewQPainter2(device)
painter.SetRenderHint(gui.QPainter__Antialiasing, true)
var shadowPath = gui.NewQPainterPath()
var path = gui.NewQPainterPath()
switch p.arrowDirection {
case ArrowDirectionUp:
painter.SetPen3(core.Qt__NoPen)
painter.SetBrush(gui.NewQBrush10(p.getShadowColor()))
var rw = p.currentProgress*float64(p.Width()-ShadowWidth*2)
var rx = 0.0
if rw < ArrowWidth+ShadowWidth*2 {
rx = p.luDis-ArrowWidth/2+2
} else {
rx = p.luDis*(1-p.currentProgress)+2
}
shadowPath.MoveTo2(rx+p.pX, ArrowWidth+2+p.pY)
shadowPath.LineTo2(p.luDis-ArrowWidth/2+p.pX, ArrowWidth+2+p.pY)
shadowPath.LineTo2(p.luDis+p.pX, 0+2+p.pY)
shadowPath.LineTo2(p.luDis+ArrowWidth/2+p.pX, ArrowWidth+2+p.pY)
shadowPath.LineTo2(rx+rw+p.pX, ArrowWidth+2+p.pY)
shadowPath.LineTo2(rx+rw+p.pX, float64(p.Height())-ShadowWidth+2+p.pY)
shadowPath.LineTo2(rx+p.pX, float64(p.Height())-ShadowWidth+2+p.pY)
shadowPath.LineTo2(rx+p.pX, ArrowWidth+2+p.pY)
painter.DrawPath(shadowPath)
painter.SetPen2(gui.NewQColor3(0x7F, 0x7F, 0x7F, 0x7F))
painter.SetBrush(gui.NewQBrush3(gui.NewQColor3(0xF5, 0xF5, 0xF5, 0xFF),1))
rw = p.currentProgress*float64(p.Width()-ShadowWidth*2)
rx = 0.0
if rw < ArrowWidth+ShadowWidth*2 {
rx = p.luDis-ArrowWidth/2
} else {
rx = p.luDis*(1-p.currentProgress)
}
path.MoveTo2(rx+p.pX, ArrowWidth+p.pY)
path.LineTo2(p.luDis-ArrowWidth/2+p.pX, ArrowWidth+p.pY)
path.LineTo2(p.luDis+p.pX, 0+p.pY)
path.LineTo2(p.luDis+ArrowWidth/2+p.pX, ArrowWidth+p.pY)
path.LineTo2(rx+rw+p.pX, ArrowWidth+p.pY)
path.LineTo2(rx+rw+p.pX, float64(p.Height())-ShadowWidth+p.pY)
path.LineTo2(rx+p.pX, float64(p.Height())-ShadowWidth+p.pY)
path.LineTo2(rx+p.pX, ArrowWidth+p.pY)
painter.DrawPath(path)
case ArrowDirectionDown:
}
painter.End()
painter.DestroyQPainter()
}
B. 动画效果.
- 实际上就是动态修改currentProgress, 以及动态设置SetMask2
func (p *PopupWidget) Show2 (interval int, f func(widget *PopupWidget)) {
if !p.isShow {
p.ticker = time.NewTicker(20 * time.Millisecond)
p.SetMask2(gui.NewQRegion2(int(p.luDis),
0,
0,
p.Height(),
gui.QRegion__Rectangle))
p.loginWidget.ShowDefault()
go func() {
defer p.ticker.Stop()
var ticker = 0
for {
select {
case <-p.ticker.C:
p.currentProgress += 20.0 / float64(interval)
if p.currentProgress > 1 {
p.currentProgress = 1
ticker = interval
}
p.SetMask2(gui.NewQRegion2(int(p.luDis*(1-p.currentProgress)),
0,
int(p.currentProgress*float64(p.Width())),
p.Height(),
gui.QRegion__Rectangle))
ticker += 20
if ticker >= interval {
p.isShow = true
if f != nil {
f (p)
}
return
}
p.Update()
}
}
} ()
}
}
C. 控件显示代码
- 这里捕获window的事件消息,我们只关心鼠标滑动的消息。
- 根据鼠标滑动的坐标,来判断应该是显示,还是隐藏loginPopupWidget
- 注意这个SetGeometry3,是自定义的,不是QT系统库函数,我想重载SetGeometry2的,不过失败了
- 代码注释也比较详细,自己理解哈。
mw.window.ConnectEvent(func(event *core.QEvent) bool {
if event.Type() == core.QEvent__HoverMove {
var pos = core.NewQPoint2(gui.QCursor_Pos().X(), gui.QCursor_Pos().Y())
var pos2 = mw.window.MapFromGlobal(pos)
var x = pos2.X()
var y = pos2.Y()
if mw.loginPopupWidget == nil {
if mw.loginWidget.Widget().Geometry().Contains3(x, y) {
mw.loginPopupWidget = NewPopupWidget (mw.window, ArrowDirectionUp, 90, 700, 90)
mw.loginPopupWidget.SetGeometry3(700, 90, 180, 100)
mw.loginPopupWidget.Show(1*1000)
mw.loginPopupWidget.SetWindowFlags(core.Qt__WindowStaysOnTopHint);
mw.loginPopupWidget.ShowNormal()
}
} else {
if !mw.loginWidget.Widget().Geometry().Contains3(x, y) &&
!mw.loginPopupWidget.Geometry().Contains3(x, y) {
mw.loginPopupWidget.Hide2(1*1000, func(widget *PopupWidget) {
if mw.loginPopupWidget != nil {
mw.loginPopupWidget.HideDefault()
mw.loginPopupWidget.DestroyQWidget()
mw.loginPopupWidget = nil
}
})
}
}
}
return mw.window.EventDefault(event)
})
|
请发表评论