Python / wxWidgets:在包装的StaticText中垂直对齐文本

时间:2013-07-22 05:57:44

标签: python wxwidgets

我在互联网上看过很多有关此事的帖子,但没有一条建议有效。

这是我的测试代码:

import wx
class DisplayText(wx.Dialog):

    def __init__(self, parent, text="", displayMode=0):

        # Initialize dialog
        wx.Dialog.__init__(self, parent, size=(480,320), style=( wx.DIALOG_EX_METAL | wx.STAY_ON_TOP ) )

        # Freeze UI so user won't see stuff flashing
        self.Freeze()

        # (For Mac) Setup a panel
        self.panel = wx.Panel(self,size=(480,320))
        self.panel.SetBackgroundColour(wx.Colour(0,0,128))

        # Setup sizer for vertical centering
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)

        # Create text field
        self.txtField = wx.StaticText(self.panel,size=(448,-1),style=wx.ALIGN_CENTRE_HORIZONTAL)
        self.txtField.SetLabel(text)
        self.txtField.Wrap(448)
        self.txtField.SetLabel(self.txtField.GetLabel())
        self.txtField.SetFont(wx.Font(36, wx.DEFAULT, wx.BOLD, 0))      
        self.txtField.SetForegroundColour(wx.Colour(255,255,255))

        # Add the static text to the sizer
        self.sizer.Add(self.txtField,1, 0,15)
        self.panel.SetSizer(self.sizer)

        # Ensure layouts are applied
        self.sizer.Layout()

        # Thaw UI
        self.Thaw()

        # Center form
        self.Center()

app = wx.App(False)

c = DisplayText(None, text="Now is the time for all good men to come to the aid of their country.")
c.Show()
import wx.lib.inspection 
wx.lib.inspection.InspectionTool().Show() 
app.MainLoop()

基于我对StaticText的理解,问题似乎是当我调用Wrap()函数时,控件包装文本但不会改变控件的大小。这意味着sizer不知道包装文本的实际垂直大小,无法正确地重新定位静态文本。

我发现一篇帖子建议使用wx.EXPAND,但这并没有解决问题。允许sizer扩展StaticText只会使StaticText填充整个框架,并且由于StaticText不会垂直居中,因此文本将最终位于窗体的顶部,而不是中心。

另一篇文章建议在sizer中试验wx.ALIGN_CENTER_VERTICAL,但这也没有帮助,因为同样的问题仍然存在 - sizer只能处理控件的大小,并且控件的大小不会在文本被包装并重新呈现。

不同的尝试导致文本被包装但在表单的顶部,只有第一行显示在表单的中心,只有第一行显示在表单的顶部,而文本没有被包裹,从而流出形式的右手边缘。但是,我所阅读的任何内容的组合都没有将表格上的包装文本垂直居中。

因此我必须能够做的是以某种方式在包装发生后垂直地找出文本的大小。这是不可能的,因为在不同的平台上,甚至在同一平台上,甚至基于文本本身,字体的垂直像素大小可能不同。所以这需要以某种方式计算。

我在想,如果能以某种方式弄清楚StaticText控件中渲染文本的实际大小,我可以显式设置控件的大小,然后让sizer完成它的工作。

这似乎应该是一件相对简单的事情......

建议将不胜感激!

1 个答案:

答案 0 :(得分:1)

关键是静态文本样式;您需要启用包装的多行样式才能工作:wx.TE_MULTILINE。

我还在面板上设置了布局,而不是sizer,但这可能与问题无关。

在我的机器上,Windows 7 64bit,我需要更改SetFont调用;你可能需要改回来。

import math
from threading import Thread
import time
import wx

e = lambda x: complex(math.cos(x), 0) + complex(0, math.sin(x))
r = lambda x: ((e(0*math.pi/3.0)*e(x)).real + 1)/2.0
g = lambda x: ((e(2*math.pi/3.0)*e(x)).real + 1)/2.0
b = lambda x: ((e(4*math.pi/3.0)*e(x)).real + 1)/2.0
colo = lambda rad: map(lambda x: int(128 * x(rad)), [r, g, b])

class DisplayText(wx.Dialog):

    def __init__(self, parent, text="", displayMode=0):

        # Initialize dialog
        wx.Dialog.__init__(self, parent, size=(480, 320), style=( wx.DIALOG_EX_METAL | wx.STAY_ON_TOP ) )

        # Freeze UI so user won't see stuff flashing
        self.Freeze()

        # (For Mac) Setup a panel
        self.panel = wx.Panel(self, size=(480, 320))
        self.panel.SetBackgroundColour(wx.Colour(0, 0, 128))
        self.panel.SetBackgroundColour(wx.Colour(*colo(0)))

        # Setup sizer for vertical centering
        self.sizer = wx.BoxSizer(wx.HORIZONTAL)
        self.panel.SetSizer(self.sizer)

        # Create text field
        self.txtField = wx.StaticText(self.panel, size=(448, -1), style=(wx.ALIGN_CENTRE_HORIZONTAL | wx.TE_MULTILINE ))
        self.txtField.SetFont(wx.Font(36, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD))      
        self.txtField.SetForegroundColour(wx.Colour(255, 255, 255))
        self.txtField.SetLabel(text)
        self.txtField.Wrap(448)
        self.sizer.Add(self.txtField, 1, 0, 15)

        # Add the static text to the sizer
        # Ensure layouts are applied
        self.panel.Layout()
        self.panel.Refresh()

        # Thaw UI
        self.Thaw()

        # Center form
        self.Center()

        self.angle = 0
        self.angle_inc = (2*math.pi)/25.0

    def change_colour(self):
        t = Thread(target=self.epilepsy_mode)
        t.start() 

    def epilepsy_mode(self):
        while True:
            time.sleep(0.02)
            self.panel.SetBackgroundColour(wx.Colour(*colo(self.angle)))
            self.panel.Refresh()
            self.angle = (self.angle + self.angle_inc) % (2*math.pi)

app = wx.App(False)

c = DisplayText(None, text="Now is the time for all good men to come to the aid of their country.")
c.Show()
#import wx.lib.inspection 
#wx.lib.inspection.InspectionTool().Show() 
c.change_colour()

app.MainLoop()