Python 在创建wx.App之前,如何初始化wx.Font对象?
我的应用程序有一个名为Python 在创建wx.App之前,如何初始化wx.Font对象?,python,wxpython,wxwidgets,Python,Wxpython,Wxwidgets,我的应用程序有一个名为gui\u constants的模块,其中包含我的应用程序使用的所有字体和颜色的定义。例如,gui\u constants.py可能包含一行 heading_font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, face='LucidaGrande') 另一个文件可能会说 heading_label = wx.StaticText(self, label='Lorem Ipsum') heading_label.SetFont(
gui\u constants
的模块,其中包含我的应用程序使用的所有字体和颜色的定义。例如,gui\u constants.py
可能包含一行
heading_font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, face='LucidaGrande')
另一个文件可能会说
heading_label = wx.StaticText(self, label='Lorem Ipsum')
heading_label.SetFont(gui_constants.heading_font)
我遇到的问题是,在创建wx.App
之前,正在导入我的gui\u常量
模块,这导致异常:
Traceback (most recent call last):
File "./main.py", line 3, in <module>
from new_gui_app import NewGuiApp
File ".../application/new_gui_app.py", line 3, in <module>
from views import MainWindow
File ".../application/views/__init__.py", line 1, in <module>
from banner import Banner
File ".../application/views/banner.py", line 3, in <module>
import gui_constants
File ".../application/gui_constants.py", line 63, in <module>
heading_font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, face='LucidaGrande')
File "/usr/local/lib/python2.7/site-packages/wx-2.9.5-osx_cocoa/wx/_gdi.py", line 2156, in __init__
_gdi_.Font_swiginit(self,_gdi_.new_Font(*args, **kwargs))
wx._core.PyNoAppError: The wx.App object must be created first!
回溯(最近一次呼叫最后一次):
文件“/main.py”,第3行,在
从新图形用户界面应用程序导入新图形用户界面应用程序
文件“../application/new\u gui\u app.py”,第3行,在
从视图导入主窗口
文件“../application/views/\uuuuu init\uuuuu.py”,第1行,在
从横幅进口横幅
文件“../application/views/banner.py”,第3行,在
导入gui_常量
文件“../application/gui_constants.py”,第63行,在
heading_font=wx.font(12,wx.SWISS,wx.NORMAL,wx.BOLD,face='LucidaGrande')
文件“/usr/local/lib/python2.7/site packages/wx-2.9.5-osx_cococa/wx/_gdi.py”,第2156行,在__
_gdi_u.Font_swiginit(self,_gdi_u.new_Font(*args,**kwargs))
wx._core.PyNoAppError:必须首先创建wx.App对象!
有人能提出一种方法,将这些“常量”声明分解成单个模块,同时防止它们在创建
wx.App
之前被初始化吗?您有两个选择。一种非常简单的方法是将常量更改为元组,而不是wx.Font对象:
heading_font = (12, wx.SWISS, wx.NORMAL, wx.BOLD, 'LucidaGrande')
然后在导入时,可以执行以下操作:
#----------------------------------------------------------------------
def create_font(data):
""""""
size, family, style, weight, face = data
font = wx.Font(size, family, style, weight, face=face)
return font
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
print type(gui_constants.heading_font)
print create_font(gui_constants.heading_font)
heading_font = "wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, face='LucidaGrande')"
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
print type(eval(gui_constants.heading_font))
您可以尝试使用Python的eval。如果这样做,您会希望将常量存储为字符串,如下所示:
#----------------------------------------------------------------------
def create_font(data):
""""""
size, family, style, weight, face = data
font = wx.Font(size, family, style, weight, face=face)
return font
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
print type(gui_constants.heading_font)
print create_font(gui_constants.heading_font)
heading_font = "wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, face='LucidaGrande')"
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
print type(eval(gui_constants.heading_font))
然后在wxPython代码中,您将执行以下操作:
#----------------------------------------------------------------------
def create_font(data):
""""""
size, family, style, weight, face = data
font = wx.Font(size, family, style, weight, face=face)
return font
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
print type(gui_constants.heading_font)
print create_font(gui_constants.heading_font)
heading_font = "wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, face='LucidaGrande')"
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
print type(eval(gui_constants.heading_font))
请注意,eval有一个小危险,即如果允许用户修改gui_常量文件,他们可能会插入恶意代码。如果他们不能修改它,那么根本就没有什么危险。我最终使用的方法是在我的
gui\u常量
模块中添加initialize
方法:
def initialize():
global heading_font
heading_font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, face='LucidaGrande')
这种方法要求用户在使用gui\u constants
中定义的任何常量之前,但在创建App
之后,调用此方法。(在应用程序
准备就绪之前调用初始化
会导致Pynapperror,如我的问题所述,调用太晚会在有人试图访问一种尚未定义的字体时产生AttributeError。)不过,时间安排并不像我想象的那么棘手;在我的App
子类的OnInit
方法的开头,我调用了initialize
,这似乎很好
还有三个其他选项(由Mike Driscoll和VZ提出):
create\u font
函数。我觉得这太重了;constants模块的所有用户都需要了解字体创建功能,这应该是一个私有的实现细节。它还增加了少量的语法开销eval
eval的危险是众所周知的,我个人的政策是除非没有其他办法,否则不要使用它FontInfo
对象,并在以后将其转换为Font
对象。这可以通过在每次使用该字体时将FontInfo
传递给某个构造器来实现,如选项(1)中所示,或者通过集体构造Font
对象,正如我在最终解决方案中所做的那样。使用前一种方法与我在第(1)项中提到的反对意见相同。使用后一种方法基本上就是我正在做的,但是有一个额外的间接层元组解决方案是最好的,我只想补充一点,在3.0中你有
wxFontInfo
,这是一个简单的元组类,也可以在GUI初始化之前创建,并且可以直接从中创建wxFont
。是的,我也这么认为,但我想给出几个选项。