2014-04-28 69 views
0

我的應用程序有一個名爲gui_constants的模塊,其中包含我的應用程序使用的所有字體和顏色的定義。例如,gui_constants.py可能包含如下如何在創建wx.App之前初始化wx.Font對象?

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_constants模塊被進口,這導致以下例外:

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! 

任何人都可以提出一種方法來保持這些「常數」的聲明因素考慮我nto單個模塊,同時也阻止它們在創建wx.App之前被初始化?

回答

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已創建。 (在App準備就緒之前調用initialize會導致PyNoAppError,就像我的問題一樣,並且調用它太遲會在有人嘗試訪問其中一種尚未定義的字體時出現AttributeError。)時序並不像我一樣棘手儘管如此,我認爲它會。我在我的App子類的OnInit方法的開頭呼叫initialize,這似乎工作正常。

有提到的其他三個選項(由麥克·德里斯科爾和VZ):

  1. 存放在一個元組的字體信息及本元組每次需要一種字體的時間傳遞給create_font功能。因爲我的口味,這太重了;常量模塊的所有用戶都需要知道字體創建函數,該函數應該是一個私有實現細節。它還在整個地方添加了少量的語法開銷。

  2. 使用evaleval的危險是衆所周知的,我個人的政策是不使用它,除非沒有別的辦法。

  3. 將字體存儲爲FontInfo對象,並稍後將它們轉換爲Font對象。這可以通過將FontInfo傳遞給某個構造函數來完成,每當我們想要使用該字體時(如選項(1)),或者通過構建整個對象(如我在最終解決方案中所做的那樣)來構建。使用前一種方法與我在第(1)項中提到的相同。使用後一種方法基本上是我正在做的,但有一個額外的間接層。

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

元組解決方案是最好的,我只是在3.0中添加了'wxFontInfo',它是一個簡單的元組類,它也可以在GUI初始化之前創建,並從'wxFont '可以直接創建。 –

+0

是的,我也這麼認爲,但我想給出幾個選項。 –