geekdoc-python-zh/docs/pythonlibrary/wxpython-learning-to-use-fo...

15 KiB
Raw Permalink Blame History

wxPython:学习使用字体

原文:https://www.blog.pythonlibrary.org/2011/04/28/wxpython-learning-to-use-fonts/

你有没有想过如何在 wxPython 中改变你的字体?那么,现在是你的幸运日,因为这正是本教程将要涵盖的内容。我们将查看以下三个项目:

  • wxPython 的内置字体
  • 字体对话框
  • wxPython 演示中的字体枚举器演示

字体是程序的重要组成部分,可以增强程序的可读性。确保你的字体大小和位置合适总是一个好主意。没错,那是常识,但有时候常识在编程中是不会发生的。哲学够了。让我们进入文章的核心部分吧!

内置字体

您可能还没有意识到这一点,但是 wxPython 有自己的一套通用字体!我不确定它们是否在所有平台上都一样,但我敢打赌它们非常接近。让我们来看一个简单的自定义演示,展示这些字体的外观:


import random
import wx
import wx.lib.scrolledpanel as scrolled

########################################################################
class MyForm(wx.Frame):

    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY, "Font Tutorial")

        # Add a panel so it looks the correct on all platforms
        panel = scrolled.ScrolledPanel(self)
        panel.SetAutoLayout(1)
        panel.SetupScrolling()

        fontSizer = wx.BoxSizer(wx.VERTICAL)
        families = {"FONTFAMILY_DECORATIVE":wx.FONTFAMILY_DECORATIVE, # A decorative font
                    "FONTFAMILY_DEFAULT":wx.FONTFAMILY_DEFAULT,
                    "FONTFAMILY_MODERN":wx.FONTFAMILY_MODERN,     # Usually a fixed pitch font
                    "FONTFAMILY_ROMAN":wx.FONTFAMILY_ROMAN,      # A formal, serif font
                    "FONTFAMILY_SCRIPT":wx.FONTFAMILY_SCRIPT,     # A handwriting font
                    "FONTFAMILY_SWISS":wx.FONTFAMILY_SWISS,      # A sans-serif font
                    "FONTFAMILY_TELETYPE":wx.FONTFAMILY_TELETYPE    # A teletype font
                    }
        weights = {"FONTWEIGHT_BOLD":wx.FONTWEIGHT_BOLD,
                   "FONTWEIGHT_LIGHT":wx.FONTWEIGHT_LIGHT,
                   "FONTWEIGHT_NORMAL":wx.FONTWEIGHT_NORMAL
                   }

        styles = {"FONTSTYLE_ITALIC":wx.FONTSTYLE_ITALIC,
                  "FONTSTYLE_NORMAL":wx.FONTSTYLE_NORMAL,
                  "FONTSTYLE_SLANT":wx.FONTSTYLE_SLANT
                  }
        sizes = [8, 10, 12, 14]
        for family in families.keys():
            for weight in weights.keys():
                for style in styles.keys():
                    label = "%s    %s    %s" % (family, weight, style)
                    size = random.choice(sizes)
                    font = wx.Font(size, families[family], styles[style], 
                                   weights[weight])
                    txt = wx.StaticText(panel, label=label)
                    txt.SetFont(font)
                    fontSizer.Add(txt, 0, wx.ALL, 5)
        panel.SetSizer(fontSizer)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(panel, 1, wx.EXPAND)
        self.SetSizer(sizer)

#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

可以清楚地看到wxPython 让您应用一个 wx。使用小部件的 SetFont 方法将字体实例添加到小部件中,该方法应用字体。最 wx。字体对象由以下内容组成:大小、字体系列(如瑞士、罗马、正常等)、字体样式(如斜体或正常)和字体粗细(如粗体或正常)。你可以将这三种特质混搭,大部分时候都能得到你想要的。如果你想使用安装在你的系统上的字体,那么,我们将在下一节讨论这个问题。应该注意的是 wx。Font class 也接受下划线、字体和编码参数,但我们不会在本文中涉及这些。有关更多信息,请查看文档。

让我们花点时间看看代码。您会注意到我们有三个 Python 字典,我们将使用它们来控制 StaticText 小部件的外观。这些字典分别包含最常见的系列、重量和样式。我们在一个三重嵌套循环中循环每个系列、粗细和样式,混合和匹配它们,创建 wx 可以用这些集合做的每种类型的标准字体。注意,我们所做的只是创建一个 wx。Font 实例,然后使用 StaticText 的 SetFont 方法将其应用于 static text。代码的其余部分应该很容易理解。很简单不是吗

现在我们将了解字体对话框。

字体对话框

对于这个例子,我们将在一个独立的脚本中使用 wxPython 的演示代码。基本上,它向您展示了如何选择字体,从选择中提取各种信息,并将设置应用到您选择的小部件。代码如下:


import wx
from wx.lib import stattext

#---------------------------------------------------------------------------

class TestPanel(wx.Panel):

    #----------------------------------------------------------------------
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        btn = wx.Button(self, -1, "Select Font")
        self.Bind(wx.EVT_BUTTON, self.OnSelectFont, btn)

        self.sampleText = stattext.GenStaticText(self, -1, "Sample Text")
        self.sampleText.SetBackgroundColour(wx.WHITE)

        self.curFont = self.sampleText.GetFont()
        self.curClr = wx.BLACK

        fgs = wx.FlexGridSizer(cols=2, vgap=5, hgap=5)
        fgs.AddGrowableCol(1)
        fgs.AddGrowableRow(0)

        fgs.Add(btn)
        fgs.Add(self.sampleText, 0, wx.ADJUST_MINSIZE|wx.GROW)

        fgs.Add((15,15)); fgs.Add((15,15))   # an empty row

        fgs.Add(wx.StaticText(self, -1, "PointSize:"))
        self.ps = wx.StaticText(self, -1, "")
        font = self.ps.GetFont()
        font.SetWeight(wx.BOLD)
        self.ps.SetFont(font)
        fgs.Add(self.ps, 0, wx.ADJUST_MINSIZE)

        fgs.Add(wx.StaticText(self, -1, "Family:"))
        self.family = wx.StaticText(self, -1, "")
        self.family.SetFont(font)
        fgs.Add(self.family, 0, wx.ADJUST_MINSIZE)

        fgs.Add(wx.StaticText(self, -1, "Style:"))
        self.style = wx.StaticText(self, -1, "")
        self.style.SetFont(font)
        fgs.Add(self.style, 0, wx.ADJUST_MINSIZE)

        fgs.Add(wx.StaticText(self, -1, "Weight:"))
        self.weight = wx.StaticText(self, -1, "")
        self.weight.SetFont(font)
        fgs.Add(self.weight, 0, wx.ADJUST_MINSIZE)

        fgs.Add(wx.StaticText(self, -1, "Face:"))
        self.face = wx.StaticText(self, -1, "")
        self.face.SetFont(font)
        fgs.Add(self.face, 0, wx.ADJUST_MINSIZE)

        fgs.Add((15,15)); fgs.Add((15,15))   # an empty row

        fgs.Add(wx.StaticText(self, -1, "wx.NativeFontInfo:"))
        self.nfi = wx.StaticText(self, -1, "")
        self.nfi.SetFont(font)
        fgs.Add(self.nfi, 0, wx.ADJUST_MINSIZE)

        # give it some border space
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(fgs, 0, wx.GROW|wx.ADJUST_MINSIZE|wx.ALL, 25)

        self.SetSizer(sizer)
        self.UpdateUI()

    #----------------------------------------------------------------------
    def UpdateUI(self):
        self.sampleText.SetFont(self.curFont)
        self.sampleText.SetForegroundColour(self.curClr)
        self.ps.SetLabel(str(self.curFont.GetPointSize()))
        self.family.SetLabel(self.curFont.GetFamilyString())
        self.style.SetLabel(self.curFont.GetStyleString())
        self.weight.SetLabel(self.curFont.GetWeightString())
        self.face.SetLabel(self.curFont.GetFaceName())
        self.nfi.SetLabel(self.curFont.GetNativeFontInfo().ToString())
        self.Layout()

    #----------------------------------------------------------------------
    def OnSelectFont(self, evt):
        data = wx.FontData()
        data.EnableEffects(True)
        data.SetColour(self.curClr)         # set colour
        data.SetInitialFont(self.curFont)

        dlg = wx.FontDialog(self, data)

        if dlg.ShowModal() == wx.ID_OK:
            data = dlg.GetFontData()
            font = data.GetChosenFont()
            colour = data.GetColour()

            self.curFont = font
            self.curClr = colour
            self.UpdateUI()

        # Don't destroy the dialog until you get everything you need from the
        # dialog!
        dlg.Destroy()

########################################################################
class MyForm(wx.Frame):

    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, wx.ID_ANY,
                          "wx.FontDialog Tutorial")
        panel = TestPanel(self)

#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()

这段代码非常简单,但还是让我们花点时间来分解它。我们最感兴趣的是 UpdateUIOnSelectFont 方法,但是不要害怕看其他的。在 init 中也有一个很好的部分,在这里我们学习如何获得应用于静态文本的字体并改变它的粗细。提示:查找定义“self.ps”的部分。

无论如何,我们将逆向工作,从 OnSelectFont 方法开始。为什么?因为它调用了另一个有趣的方法!首先,我们需要创建一个 wx。FontData 对象,它将保存与我们稍后在字体对话框中选择的字体相关的信息。然后,我们将对象的当前颜色和字体设置为当前字体的设置。接下来我们创建一个 wx。FontDialog 实例并显示对话框!这里我们取出所有我们需要的字体数据,在这个例子中,是颜色和字体,然后我们调用我们的更新方法。

UpdateUI 方法中,我们将一个静态文本控件设置为选择的字体。然后,我们从当前选择的字体中提取各种信息,并在适当的标签中显示这些信息。如您所见,我们选择提取点大小、系列、样式、粗细、字体和原生字体信息。现在我们可以进入最后一个演示了!

FontEnumerator

这个例子也取自 wxPython 演示。这是它对 wx 的评价。FontEnumerator 小工具:

wxFontEnumerator 枚举系统中所有可用的字体,或者只枚举具有给定属性的字体——或者只枚举固定宽度的字体(适用于终端模拟器等程序),或者枚举给定编码中可用的字体。

在我的 Windows XP 机器上,似乎是系统上所有可用的字体。以下是供您阅读的代码:


# fontEnumDemo.py

import wx

########################################################################
class TestPanel(wx.Panel):

    #----------------------------------------------------------------------
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1)

        e = wx.FontEnumerator()
        e.EnumerateFacenames()
        elist= e.GetFacenames()

        elist.sort()

        s1 = wx.StaticText(self, -1, "Face names:")

        self.lb1 = wx.ListBox(self, -1, wx.DefaultPosition, (200, 250),
                             elist, wx.LB_SINGLE)

        self.Bind(wx.EVT_LISTBOX, self.OnSelect, id=self.lb1.GetId())

        self.txt = wx.StaticText(self, -1, "Sample text...", (285, 50))

        row = wx.BoxSizer(wx.HORIZONTAL)
        row.Add(s1, 0, wx.ALL, 5)
        row.Add(self.lb1, 0, wx.ALL, 5)
        row.Add(self.txt, 0, wx.ALL|wx.ADJUST_MINSIZE, 5)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(row, 0, wx.ALL, 30)
        self.SetSizer(sizer)
        self.Layout()

        self.lb1.SetSelection(0)
        self.OnSelect(None)
        wx.FutureCall(300, self.SetTextSize)

    #----------------------------------------------------------------------
    def SetTextSize(self):
        self.txt.SetSize(self.txt.GetBestSize())

    #----------------------------------------------------------------------
    def OnSelect(self, evt):
        face = self.lb1.GetStringSelection()
        font = wx.Font(28, wx.DEFAULT, wx.NORMAL, wx.NORMAL, False, face)
        self.txt.SetLabel(face)
        self.txt.SetFont(font)
        if wx.Platform == "__WXMAC__": self.Refresh()

########################################################################
class MyForm(wx.Frame):

    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None,
                          title="wx.FontEnumerator Tutorial",
                          size=(800,600))
        panel = TestPanel(self)

#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm()
    frame.Show()
    app.MainLoop()

好吧,这个代码也很简单。你会问,这是怎么回事?好吧,我们在和 Python 打交道就是这样Python 就是摇滚!让我们分解这段代码,看看发生了什么。看起来我们需要做的就是创建一个 wx.FontEnumerator 的实例...至少在演示中没有,文档中也没有提到。接下来我们列举字体名称。最后,我们创建一个人脸名称列表,对它们进行排序,并将列表放在一个 wx 中。列表框

注意:在最初的演示中作者使用“list”作为下一行的变量名但是由于这是 Python 中的一个关键字(通常是非常糟糕的形式)本例中的代码用“elist”替换了“list”。

下一段有趣的代码发生在 OnSelect 方法中,每当用户选择列表框中的一个项目时就会触发该方法。正如您可能已经猜到的那样,我们从 ListBox 中获取了 face name并使用它来创建一个字体然后将该字体应用于一个静态文本小部件。这让我们可以看到字体的样子。

包扎

现在你应该知道如何使用 wxPython 的标准字体以及加载到你的机器上的字体。您现在也知道了如何提取关于特定字体的大量信息,这在排除字体不按预期方式运行的故障时可能会派上用场。请记住,除了 StaticText 小部件之外,您还可以将这些字体应用于其他地方。事实上,大多数小部件都有一个 SetFont 方法,所以您可以将您的字体首选项应用到大多数用户界面。

进一步阅读

源代码