wx.Font 使用面孔名称 & PIL.ImageFont 使用文件名...有什么方法可以将两者联系起来吗?
嘿伙计们,抱歉,但这将是一个大问题..;)
我现在遇到了一个烦人的小障碍。我正在创建一个 RSS 风格的工作应用程序,该应用程序将放置在办公室的一些大型 LCD 显示屏上。基本概念是建立一个客户端/服务器设置,用户可以使用自定义编辑器使用他们选择的字体、粗细、大小等创建单独的文章,然后将它们上传到服务器(最初)将显示文本在 LCD 屏幕上使用 wx.TextCtrl & wx.TextAttr。
这就是我要发疯的地方..
我能够顺利地创建客户端/服务器,我可以让服务器的显示正常工作,但我无法找到一种方法来从右到左流式传输文本而不会导致任何闪烁。我们的显示器是 42 英寸,我尝试使用多种方法来完成此任务,但由于这些显示器所需的文本大小,我似乎无法摆脱闪烁。
到目前为止,我已经尝试了三种方法来使文本动起来:
方法 1:wx.Ticker()
这是一个控件,它似乎完全符合我一直试图完成的目标,并且当使用较小的字体它实际上完全符合我的需要。问题是我们不能使用较小的字体,我们将使用的字体会很大,如 36、48、72 等,当使用 wxpython 演示测试股票代码时,我无法创建足够平滑的效果来考虑即使在稍微调整了他们的代码之后,这也是完成我的任务的可行方法。
方法 2:FadingTextCtrl()(自定义控件)
不久前,在我找到 wx.Ticker 之前,我已经创建了一个控件来完成此任务,并且在之前的几个例子中我已经成功地使用了它项目。我基本上设置了一个带有 EVT_TIMER 的 TextCtrl,将光标设置到行首,然后重复删除文本的第一个字符,速度由 EVT_TIMER 控制。这令人惊讶地降低了闪烁的频率,但当它确实选择闪烁时,它会更加明显。另一个缺点是您需要使用固定宽度的字体以避免删除字符时出现跳跃。如果没有固定宽度的字体,由于宽度的变化,某些字符会比其他字符删除得更快,从而导致文本的运动看起来加速且缓慢。随机下降,无法准确控制速度。
方法三:wx.AnimatedCtrl() &自定义生成的动画 GIF
这似乎是我迄今为止最好的选择。我已经非常接近了!
使用 PIL 以及我通过 Google 找到的一些随机片段,我已经能够生成动画 GIF 并将其放置在 wx.AnimatedCtrl() 中。在大屏幕上进行了一些测试后,我终于找到了解决方案,因为文本流式传输而没有任何闪烁!在向 gif 添加更多帧后,我能够比以前的任何方法更平滑地移动文本。所以就是这样,没有闪烁,完全平滑,然后最荒谬的冲突把我打傻了......
在构建了一个适合按需创建图像的函数后,我回到我的 GUI 并开始链接我的所有控件,收集用于创建动画 GIF 的所有文本及其属性。我将其全部推送到我的函数中,然后我突然意识到,在 wx 中创建字体的方式与使用 PIL 的方式不同,更具体地说,您如何指定计划在文本中使用哪种字体。例如,wx.Font()使用字体的Facename来指定要使用的字体,其中PIL.ImageFont使用字体的路径/文件名来选择要使用的字体。
你一定是在开玩笑吧……我现在距离完成我的项目只有一步之遥,但我却因为无法关联我的字体而被打了一巴掌。我可以推送其余的字体信息,但我无法告诉 PIL.ImageFont 使用 wx.Font() 提供的字体数据使用哪种字体。
所以最后,这是我的问题...我如何将 wx.Font() 中的面孔名称与它们的实际文件名相关联,以便我可以找到一种方法来告诉 PIL.ImageFont 使用我用控件定义的文本属性?
昨晚,当我找到注册表项时,我以为我中了大奖:
"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts"
该注册表项包含一堆字符串值,这些值定义了 Window 的可用字体名称,以及其文件的相关路径。这与控制面板>>使用的信息相同。字体所以你会认为这是我丢失的链接。我快速构建了另一个模块来索引值并为文本生成选定的面名/文件名。这对于 TTF (TrueType) 字体来说似乎工作得很好。
然后又出现了另一个问题。
大多数 Facename 使用多个字体文件来产生斜体、粗体等效果,但使用 wx.Font() 时,您似乎总是使用同一个 Facename 作为字体,例如“Tahoma”,并指定因此,对于 Tahoma 常规,您将使用字体文件“TAHOMA.TTF”,但要使用 Tahoma Bold,您将使用字体文件“tahomabd.ttf”。话虽这么说,在注册表中找到的面孔名称与 wxPython 中使用的面孔名称不正确匹配。例如:Tahoma 的注册界面名称可以是 Tahoma (TrueType) 或 Tahoma Bold (True Type) 粗体,尽管 wx.Font() 只需要“Tahoma”两者,并且它将在幕后使用匹配适当的字体文件您提供给控件的其他参数。删除注册表中的面孔名称中的垃圾文本很容易,例如(TrueType)或(VGA res),但我仍然留下某些字体的多个面孔名称,这根本行不通。
现在这就是我现在所处的位置。
我使用 PIL 通过创建画布、设置所有文本属性来创建动画 gif
创建两个列表,一个用于文本,一个用于每个文本项的属性。例如:
msgs = ["*** ", "标题:", "要打印到图像文件的消息正文。还有什么可说的?真的?!?!?!那里有什么? !?”,“***”]
字体 = [(font_bold_file, 48, "#000000"), (font_bold_file, 48, "#000000"), (font_norm_file, 48, "#000000"), (font_bold_file, 48, "#000000" ")]
创建一个空白画布,将文本范围的宽度加倍
- 迭代列表,将文本写在画布上,右对齐,每帧稍微将文本的 posX 向左移动。
为了避免 wx.Font 和 PIL.ImageFont 之间的面名/文件名冲突,我想我应该首先使用 wxPython 中的文本及其所有属性创建一个位图,然后将其转换为 PIL 图像。然后,我不应该使用 PIL.ImageFont 绘制文本,将文本的位置稍微移动到每帧上,而应该将转换后的 wxBitmap 粘贴到画布上,使用 PIL.Image 的粘贴将整个位图稍微移动到每帧上?
我在这里遇到的问题是找到正确的方法来使用任何 wx 的 DC(ClientDC、PaintDC、(Auto)BufferedDC、MemoryDC)来创建位图。到目前为止,我能够使用 wxMemoryDC & wxBitmap 将文本写入位图,但到目前为止,我找不到一种方法来设置位图的完整 VirtualSize 以包含整个图像,因为它似乎仅限于窗口的 ClientSize。我会从一开始就指定完整大小,但在获得消息的文本范围之前我没有该信息。从长远来看,我更愿意创建 wxBitmap,甚至不将其显示在控件中,因为它的唯一目的是传递给 PIL 进行进一步处理。
所以这是我请求帮助的地方!有人可以告诉我如何找到一种将 wx.Font 与 PIL.ImageFont 关联起来的方法,这样我就可以使用我的动画 gif 生成器来完成它已经设置要做的事情,或者帮助解释一下如何使用 wxPython 创建位图,以及绘制文本,以便所有文本都出现在位图中,而不管当前的 ClientSize 如何?我可以轻松地将位图转换为 PIL,我只需要先弄清楚如何使用 wx 创建它!
非常感谢任何可以提供帮助的人,并对超长的帖子表示歉意,但我应该在几周前完成这个项目。每当我以为我已经解决了这个问题时,这个可笑的字体问题就不断地打我!由于这是一个工作项目,如果您需要任何代码示例,请请求,我将制作一些不包含任何与工作相关的信息的东西。
Hey guys, sorry but this is going to be a big one.. ;)
I'm running into an annoying little snag right now. I'm creating an RSS-style app for work which will be placed on some large LCD displays across the office. The basic concept is to have a client/server setup where the user would use a custom editor to create the individual articles with their chosen fonts, weights, sizes, etc. and then upload them to the server which (originally) would display the text on the LCD screens using a wx.TextCtrl & wx.TextAttr.
Here is where I am going nuts..
I was able to create the client/server without a hitch, I can get the server's display to work correctly, but I am unable to find a method to stream the text from right to left without causing any flicker. Our displays are 42 inch and I have tried using quite a few methods to accomplish this task but with the text sizes needed for these display's I just can't seem to get rid of the flickering.
So far I have tried three methods to get the text in motion:
Method 1: wx.Ticker()
This is a control that appeared to do exactly what i have been trying to accomplish, and when using smaller fonts it actually does exactly what I need. The Problem is that we cannot use smaller fonts, the fonts we will be using will be quite large, like 36, 48, 72, etc. and when testing the ticker with the wxpython demo I was unable to create a smooth enough effect to consider this a feasible way to accomplish my task, even after tweaking their code a bit.
Method 2: FadingTextCtrl() (Custom control)
A while back, and well before I found the wx.Ticker, I had created a control to accomplish this feat and I have used it successfully within a few previous projects. I basically setup a TextCtrl with an EVT_TIMER, set the cursor to the beginning of the line and then repeatedly removed the first character of the text, speed is controlled by a EVT_TIMER. This surprisingly lessened the frequency of the flickering but when it did choose to flicker, it was much more noticeable. Another downfall is that you need to use a fixed-width font to avoid jumpiness when deleting characters. Without a fixed-width font, some characters will delete faster then others due to their changing widths, causing the motion of the text to appear to speed up & down randomly which makes it impossible to accurately control the speed.
Method 3: wx.AnimatedCtrl() & a custom generated animated GIF
This seems to be my best bet so far. AND I AM SOOOOOOOOO CLOSE!!!
Using PIL, and some random snippets I was able to find through Google along the way, I have been able to generate an animated GIF and place it in a wx.AnimatedCtrl(). After doing some testing on the big screens it FINALLY looked like I had my solution as the text streamed on by without a single flicker! After adding some more frames to the gif I was able to have the text move across more smoothly then with any of the previous methods. So here it is , no flickering, complete smoothness, and then the most ridiculous conflict slapped me silly...
After building a function suitable to create my images on demand I went back to my GUI and started to link all of my controls, gathering all of my text and their attributes to create the animated GIF with. I go to push it all to my function and then it strikes me that the way you would create your fonts in wx is different then the way you would with PIL, more specifically how you designate which font you plan to use for your text. For example, a wx.Font() uses the Facename of a font to designate the font to be used, where PIL.ImageFont uses a path/filename of the font to select the font to draw with.
You have to be kidding me..... I am now just one step away from completing my project and I get slapped with no way to relate my fonts. I can push the rest of the font information in but I can't tell PIL.ImageFont which font to use with the font data provided by wx.Font().
So finally, here's my question... How can I relate the facenames from wx.Font() with their actual filename's so I can find a way to tell PIL.ImageFont to use the text attributes I have defined with my controls?
I thought I hit the jackpot last night when I found the registry key:
"HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts"
This key contains a bunch of string values which defines Window's available font facename's, and the relevant paths to their files. This is the same information used by Control Panel >> Fonts so you would think this was my missing link. I quickly built another module to index the values and produce the selected facename/filename for the text. This appeared to work just fine for the TTF (TrueType) fonts.
And then ANOTHER snag hits..
Most Facename's use multiple font files to produce effects like italic, bold, etc. but with wx.Font() it appears that you always use the one facename for the font, like "Tahoma", and designate the effects with other arguments like style, weight, etc. So for Tahoma regular, you would use the font file "TAHOMA.TTF" but to use Tahoma Bold you would use the font file "tahomabd.ttf". That being said, The facenames found in the registry do not properly match with the facenames used in wxPython. For example: regsitry facename for Tahoma can be either Tahoma (TrueType) or Tahoma Bold (True Type) for bold, although wx.Font() just wants "Tahoma" for both, and it will match the appropriate font files behind the scenes using the other arguments you provided to the control. It was easy to remove the junk text in the registry facename's, like (TrueType) or (VGA res), but I am still left with multiple facenames for certain fonts, which just doesn't fly.
Now here is where I am currently at.
I use PIL to create my animated gif by creating a canvas, setting all of the text attributes
create two lists, one for the text, one for the attributes for each text item. eg:
msgs = ["*** ", "Header: ", "The message body to print to the image file. What else is there to say?? REALLY?!?!?! WHAT IS THERE?!?", " ***"]
fonts = [(font_bold_file, 48, "#000000"), (font_bold_file, 48, "#000000"), (font_norm_file, 48, "#000000"), (font_bold_file, 48, "#000000")]
create a blank canvas, double the width of the text extent
- iterate through the lists, writing the text on the canvas, right-justified, slightly moving the text's posX to the left per frame.
To avoid the facename/filename conflict between wx.Font and PIL.ImageFont I was thinking I should first create a bitmap with the text and all of it's attributes in wxPython, then convert it to a PIL image. Then instead of drawing the text with PIL.ImageFont, moving the position of the text slightly over per frame, I should just paste the converted wxBitmap onto the canvas, slightly moving the whole bitmap over per frame using PIL.Image's paste?
The issue I am running into here is finding proper way to use any of wx's DC's (ClientDC, PaintDC, (Auto)BufferedDC, MemoryDC) to create the bitmap with. So far I am able to use a wxMemoryDC & wxBitmap to write the text to the bitmap but so far I cannot find a way to set the full VirtualSize of the bitmap to contain the whole image as it seems to be limited to the window's ClientSize. I would have designated the full size from the start but I do not have that information until I get the text extent of the message. In the long run I would prefer to create the wxBitmap without even displaying it in a control as it's only purpose will be to be passed to PIL for further processing.
So here is where I beg for help!! Can somebody PLEASE PLEASE shed some light on how I can can either find a way to relate wx.Font with PIL.ImageFont so I can just use my animated gif generator to do what it already is setup to do, or help shed some light on how I can create a bitmap using wxPython, as well as draw in my text so that all of the text is present within the bitmap, regardless of the current ClientSize? I can easily convert the bitmap to PIL, I just need to figure out how to create it in with wx first!
A HUGE THANKS IN ADVANCE to anyone that can help, and my apologies for the super long post, but I should have had this project complete weeks ago. This ridiculous font issue keeps slapping me around every time I think I've figured it out! Being it that this is a project for work, If you require any code samples please request and I'll whip something up without any work-related info in it.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您是否考虑过使用 wx.MemoryDC 与双 -缓冲窗口(即“位块传送”)?基本技术是将文本绘制到屏幕外的 DC 中,然后将其“blit”到屏幕上。这消除了闪烁。
这是 wx wiki 中的关于消除闪烁的讨论。
这里有一个 wxpython wiki 中的双缓冲的讨论。
Have you looked into using wx.MemoryDC with a double-buffered window (i.e. "bit blitting")? The basic technique is that you draw your text into the DC off-screen, and then "blit" it onto the screen. This eliminates flicker.
Here's a discussion about eliminating flicker in the wx wiki.
And here's a discussion of double buffering in the wxpython wiki.
很久以前忘记回答这个问题了......
关于字体的相关性,从长远来看,我无法找到可行的方法来完成这项任务。
根据 Christopher 提出的建议,我能够生成一个带有指定文本的动画 GIF 大大解决了运动问题。
不幸的是,我无法提供示例,因为该项目是我几年前工作过的一家公司的项目,目前我无法访问源代码。
Forgot to answer this long ago...
With regards to relating the fonts, in the long run I was not able to find a feasible method to accomplish this task.
Using the suggestions made by Christopher, I was able to generate an animated GIF with the specified text which cleared up the motion issue quite a bit.
Unfortunately I am unable to provide an example as this project was for a company I worked for a few years back and I do not have access to the source code at this time.