我的应用程序有一个名为gui_constants
的模块,其中包含我的应用程序使用的所有字体和颜色的定义。例如,gui_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)
我遇到的问题是我的gui_constants
模块是在创建wx.App
之前导入的,这会导致异常:
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!
任何人都可以建议一种方法来将这些“常量”声明保留在一个模块中,同时也阻止它们在wx.App
创建之前被初始化吗?
答案 0 :(得分:1)
你有几个选择。一个非常简单的方法是将常量更改为元组而不是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)
您可以尝试的替代方法是使用Python的 eval 。如果你这样做,你会希望将常量存储为字符串,如下所示:
heading_font = "wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, face='LucidaGrande')"
然后在你的wxPython代码中,你可以这样做:
########################################################################
class MyPanel(wx.Panel):
""""""
#----------------------------------------------------------------------
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent)
print type(eval(gui_constants.heading_font))
请注意,eval的危险性很小,如果允许用户修改gui_constants文件,则可能会插入恶意代码。如果他们无法对其进行修改,那么根本没有任何危险。
答案 1 :(得分:0)
我最终使用的方法是在我的initialize
模块中添加gui_constants
方法:
def initialize():
global heading_font
heading_font = wx.Font(12, wx.SWISS, wx.NORMAL, wx.BOLD, face='LucidaGrande')
此方法要求用户在使用gui_constants
中定义的任何常量之前调用此方法,但在创建App
之后。 (在initialize
准备好之前调用App
会导致PyNoAppError,如我的问题所示,当有人试图访问其中一个尚未定义的字体时,调用它太晚会产生AttributeError。)然而,时机并不像我想象的那样棘手;我在initialize
子类的App
方法的开头调用OnInit
,这似乎工作正常。
提到了另外三个选项(Mike Driscoll和VZ):
将字体信息存储在元组中,并在每次需要字体时将此元组传递给create_font
函数。根据我的喜好,这太重了;常量模块的所有用户都需要知道字体创建功能,该功能应该是私有实现细节。它还在整个地方添加了少量语法开销。
使用eval
。 eval
的危险性众所周知,我的个人政策是不使用它,除非别无其他。
将字体存储为FontInfo
个对象,稍后将其转换为Font
个对象。这可以通过将FontInfo
传递给某个构造函数来完成每次我们想要使用该字体,如选项(1),或通过构建Font
对象,就像我在最终解决方案中所做的那样。使用前一种方法与我在项目(1)中提到的具有相同的反对意见。使用后一种方法基本上就是我正在做的,但是有一个额外的间接层。