Статьи

wxPython: обучение использованию шрифтов

Задумывались ли вы о том, как изменить свой шрифт в 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.Font к вашему виджету, используя метод SetFont виджета , который применяет шрифт. Большинство объектов wx.Font состоят из следующих элементов: размер, семейство шрифтов (т. Е. Швейцарский, римский, нормальный и т. Д.), Стиль шрифта (т. Е. Курсив или обычный) и вес шрифта (т. Е. Жирный или обычный). Вы можете смешивать и сочетать эти три характеристики, чтобы получить то, что вы хотите большую часть времени. Если вы хотите использовать шрифт, установленный в вашей системе, мы вернемся к этому в следующем разделе. Следует отметить, что класс wx.Font также принимает аргументы подчеркивания, лица и кодирования, но мы не будем рассматривать их в этой статье. Проверьте документацию для получения дополнительной информации.

Давайте на минутку посмотрим на код. Вы заметите, что у нас есть три словаря Python, которые мы будем использовать для управления внешним видом виджета StaticText. Эти словари содержат наиболее распространенные семейства, веса и стили соответственно. Мы перебираем каждое семейство, вес и стиль в тройном вложенном цикле, смешиваем и сопоставляем их, чтобы создать любой тип стандартного шрифта, который wx может использовать с этими наборами. Обратите внимание, что все, что мы делаем, это создаем экземпляр wx.Font и затем применяем его к StaticText, используя последний метод SetFont . Остальной код должен быть довольно простым для понимания. Довольно просто, нет?

Теперь мы собираемся узнать о диалоге шрифта.

Диалог шрифтов

В этом примере мы будем использовать демонстрационный код 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()

Этот код довольно прост, но давайте в любом случае уделим ему немного времени. Нас больше всего интересуют
методы
UpdateUI и
OnSelectFont , но не бойтесь смотреть на все остальное. В __init__ есть и полезная часть
, где мы узнаем, как получить шрифт, примененный к StaticText, и изменить его вес. Подсказка: найдите раздел, в котором определен «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, вот что! Питон просто качается! Давайте разберем этот код и посмотрим, что происходит. Похоже, все, что нам нужно сделать, это создать экземпляр wx.FontEnumerator. Обратите внимание, что он не принимает никаких аргументов … по крайней мере, это не так, как в демоверсии, и в документации тоже не упоминается. Далее перечисляем имена шрифтов. Наконец, мы создаем список имен лиц, сортируем их и помещаем список в wx.ListBox .

Примечание: в оригинальной демонстрации автор использовал «список» в качестве имени переменной для следующей строки, но, поскольку это ключевое слово в Python (и в целом очень плохая форма), код в этом примере заменил «список» на « псписок».

Следующий интересный фрагмент кода происходит в методе OnSelect , который запускается всякий раз, когда пользователь выбирает элемент в списке. Как вы уже догадались, мы берем имя лица из ListBox и используем его для создания шрифта, который затем применяется к статическому текстовому виджету. Это позволяет нам увидеть, как выглядит шрифт.

Завершение

Теперь вы должны знать, как использовать стандартные шрифты wxPython, а также те, которые загружены на ваш компьютер. Теперь вы знаете, как извлечь много информации о конкретном шрифте, что может пригодиться при устранении неполадок, почему шрифт работает не так, как вы ожидаете. Помните, что вы можете применять эти шрифты не только к виджету StaticText. Фактически, большинство виджетов имеют метод SetFont, так что вы можете применить настройки шрифта к большей части вашего пользовательского интерфейса.

Дальнейшее чтение

Исходный код


Источник: http://www.blog.pythonlibrary.org/2011/04/28/wxpython-learning-to-use-fonts/