实现更美观的滚动字幕效果
之前虽然通过设置窗口样式去掉了标题栏,但是背景看起来还是有些碍眼。通过 SetTransparent 只能调整整体透明度,文字和背景都透明了。希望实现的效果是背景透明,而文字不透明。
透明背景的文字窗体
wxPython demo 中有两个实现形状窗口的例子,ShapedWindow 和 AdvancedSplash,其实都是通过 SetShape(wx.Region) 实现的。region 翻译为区域,不太理解,还有另一个签名 SetShape(wx.GraphicsPath),所以实际是设置像 PS 里的路径?
没有找到怎么用文字来设置形状,所以把文字先转为图像。通过 wx.GraphicsContext 创建透明背景文字 Bitmap,把图像设置为 Frame 的 shape。显示文字会有明显锯齿,且当字体设置较小时,文字周围会有黑边。
在 OnPaint 中绘制一个文字颜色的同窗口大小的矩形,文字黑边消失。后绘制的矩形是显示在文字上层,文字图片变成蒙版了?
效果:

源码:
# -*- coding: utf-8 -*-
import wx
class MyFrame(wx.Frame):
def __init__(self, *args, **kwargs):
super(MyFrame, self).__init__(*args, **kwargs)
self.Center()
w, h = self.GetSize()
self.bg = wx.Bitmap.FromRGBA(w, h)
dc = wx.MemoryDC(self.bg)
gc = wx.GraphicsContext.Create(dc)
font = wx.Font(32, family=wx.SWISS, style=wx.NORMAL, weight=wx.BOLD, faceName=u"宋体")
gc.SetFont(font, "#ff0000")
gc.DrawText(u"你好,世界!Hello World!😍", 0, 0) # emoji 不能显示
region = wx.Region(self.bg, wx.TransparentColour)
self.SetShape(region)
self.Bind(wx.EVT_PAINT,self.onPaint)
self.SetTransparent(150)
def onPaint(self, evt):
dc= wx.PaintDC(self)
dc.DrawBitmap(self.bg, 0, 0, True)
dc.SetBrush(wx.Brush(wx.RED))
dc.DrawRectangle(0, 0, *self.GetSize())
app = wx.App()
frame = MyFrame(parent=None,
size=(1075, 53),
style=wx.FRAME_SHAPED | wx.NO_BORDER | wx.STAY_ON_TOP | wx.TRANSPARENT_WINDOW)
frame.Show()
app.MainLoop()
还有一种方法,直接通过 wx.ScreenDC 在电脑屏幕上任意位置绘制文字,不需要交互的话应该是可以的。脱离了程序窗口,如果和鼠标、键盘交互,要怎么处理呢?
锯齿问题待解决,使用 SetAntialiasMode 方法设置没有效果。抗锯齿参考帖子 https://discuss.wxpython.org/t/anti-aliased-text-with-wx-graphicscontext/25021/27
wx.GraphicsContext wraps GDI+, which is a system API, so it is still dependent on the system settings for AA. You could try using wx.lib.graphics.GraphicsContext instead, it uses Cairo on all the platforms instead of the native APIs.
来源:https://discuss.wxpython.org/t/anti-aliased-text-with-wx-graphicscontext/25021/4
大略就是自带的 GDI 是调用系统 API,需要使用优化的第三方库。后续再尝试。
整合滚动字幕
向歌词工具进发?下面是某音乐播放器的歌词显示效果。SetShape 方法传递一个空的 wx.Region 就能使原本的矩形窗口显示出来,可以用来实现歌词的鼠标移入移出效果。文字描边怎么实现的?还是先继续整合滚动弹幕吧。

wx.lib.ticker.Ticker 类是继承自 wx.Control , 而 SetShape 方法是继承自 wx.NonOwnedWindow,不能作用于 Ticker。直接继承 wx.Frame 重写 Ticker 控件?好像并不需要做很大改动,直接把基类改一下就能用。
还有些待完善:1.多线程用法;2.清空形状图像(如果用 wx.GCDC 的 Clear 也会显示矩形窗体);3.文字窗体用鼠标点击时,文字镂空范围是选择不到的,需要歌词那样的效果。

源码:
# -*- coding: utf-8 -*-
# Author: SmileBasic
import threading
import wx
import ticker
class Ticker(ticker.Ticker):
def __init__(self, *args, **kwargs):
self._text = [] # 滚动字符串存储列表,格式[[字符串尺寸, 字符串], [(56, 22), "test"]]
self._text_max = 500 # _text 最大可存储字符串数量
self._gap = 0 # 滚动字符串之间间距
self._gap_pixels = 0
self._index = 0 # 显示字符串头节点
self._num = 1 # 显示字符串数量
self._dc = wx.MemoryDC() # 用于获取文本尺寸
super(Ticker, self).__init__(*args, **kwargs)
self.Center()
self._bg = wx.Bitmap.FromRGB

文章介绍了如何使用wxPython库创建具有透明背景的滚动字幕效果。通过wx.GraphicsContext和wx.Region设置窗口形状,实现了文字不透明而背景透明。作者遇到了文字锯齿和交互问题,并探讨了使用wx.ScreenDC直接在屏幕上绘制文字的可能性。同时,文章展示了如何通过Ticker类实现滚动字幕功能,包括文字存储、滚动更新和鼠标交互。最后提到了关联其他程序窗口以显示内容的尝试,但未达到预期效果,提出了进一步的美化和优化方向。
最低0.47元/天 解锁文章
7097

被折叠的 条评论
为什么被折叠?



