2011-02-28 66 views
2

我的应用程序有一个3行的主boxsizer。前两行是文本控件,第3行是用于执行不同动作的按钮选择wxPython sizer调整大小不正确

当我的应用程序启动时,其大约占整个窗口下面的整个窗口空间的1/3,即空白区域。当我调整窗口大小以减小空间时,它实际上会压缩我的文本控件而不是删除空白区域。为什么?

#Boa:Frame:Frame1 

import wx 
import os 
import glob 
import shutil 
import datetime 
from mutagen.mp3 import MP3 
from mutagen.easyid3 import EasyID3 
import mutagen.id3 
import unicodedata 

from ObjectListView import ObjectListView, ColumnDefn 



########################################################################  
class Track(object): 
    def __init__(self, title, artist, album, source, dest): 
     """ 
     Model of the Track Object 
     Contains the followign attributes: 
     'Title', 'Artist', 'Album', 'Source', 'Dest' 
     """ 

     self.atrTitle = title 
     self.atrArtist = artist 
     self.atrAlbum = album 
     self.atrSource = source 
     self.atrDest = dest   


class Action(object): 
    def __init__(self, timestamp, action, result): 
     self.timestamp = timestamp 
     self.action = action 
     self.result = result 

######################################################################## 
# Non GUI 
######################################################################## 

def selectFolder(sMessage): 
    print "Select Folder" 
    dlg = wx.DirDialog(None, message = sMessage) 

    if dlg.ShowModal() == wx.ID_OK: 
     # User has selected something, get the path, set the window's title to the path 
     filename = dlg.GetPath() 
    else: 
     filename = "None Selected" 

    dlg.Destroy() 
    return filename 

def getList(SourceDir): 
    print "getList" 
    listOfFiles = None 
    print "-list set to none" 

    listOfFiles = glob.glob(SourceDir + '/*.mp3') 

    return listOfFiles 

def getListRecursive(SourceDir): 
    print "getListRecursive" 
    listOfFiles = None 
    listOfFiles = [] 
    print "-list set to none" 

    for root, dirs, files in os.walk(SourceDir): 
     for file in files: 
      if file.endswith(".mp3"): 
       listOfFiles.append(os.path.join(root,file)) 

    #print listOfFiles 

    return listOfFiles 

def strip_accents(s): 
    print "strip_accents" 
    return ''.join((c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn')) 

def replace_all(text): 
    print "replace_all " + text 
    dictionary = {'\\':"", '?':"", '/':"", '...':"", ':':"", '&':"and"} 

    print "-- repl_orig: " + text 
    print "-- repl_decode: " + text.decode('utf-8') 

    text = strip_accents(text.decode('utf-8')) 

    for i, j in dictionary.iteritems(): 
     text = text.replace(i,j) 

    return text 

def getTitle(fileName): 
    print "getTitle" 
    audio = MP3(fileName) 

    try: 
     sTitle = str(audio["TIT2"]) 
    except KeyError: 
     sTitle = os.path.basename(fileName) 
     frame.lvActions.Append([datetime.datetime.now(),fileName,"Title tag does not exist, set to filename"]) 

    # TODO: Offer to set title to filename 
    ## If fileName != filename then 
    ## prompt user for action 
    ## Offer Y/n/a 

    sTitle = replace_all(sTitle) 

    return sTitle 

def getArtist(fileName): 
    print "get artist" 

    audio = MP3(fileName) 

    try: 
     sArtist = str(audio["TPE1"]) 
    except KeyError: 
     sArtist = "unkown" 
     frame.lvActions.Append([datetime.datetime.now(),fileName,"Artist tag does not exist, set to unkown"]) 

    #Replace all special chars that cause dir path errors 
    sArtist = replace_all(sArtist) 

    #if name = 'The Beatles' change to 'Beatles, The' 
    if sArtist.lower().find('the') == 0: 
     sArtist = sArtist.replace('the ',"") 
     sArtist = sArtist.replace('The ',"") 
     sArtist = sArtist + ", The" 

    return sArtist 

def getAblum(fileName): 
    print "get album" 
    audio = MP3(fileName) 

    try: 
     sAlbum = str(audio["TALB"]) 
    except KeyError: 
     sAlbum = "unkown" 
     frame.lvActions.Append([datetime.datetime.now(),fileName,"Album tag does not exist, set to unkown"]) 

    #Replace all special chars that cause dir path error  
    sAlbum = replace_all(sAlbum) 
    return sAlbum 


######################################################################## 
# GUI 
######################################################################## 
class MainPanel(wx.Panel): 
    #---------------------------------------------------------------------- 
    def __init__(self, parent): 
     wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY) 

     #Create static box frames for GUI features 
     self.stTracks = wx.StaticBox(self, -1, "Tracks") 
     self.stEvents = wx.StaticBox(self, -1, "Events") 
     self.stFolders = wx.StaticBox(self, -1, "Folders") 
     self.stOptions = wx.StaticBox(self, -1, "Options") 
     self.stActions = wx.StaticBox(self, -1, "Actions") 
     self.stSearch = wx.StaticBox(self, -1, "Search")  

     #Create Track Object List - editable 
     self.TrackOlv = ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT|wx.SUNKEN_BORDER) 
     self.TrackOlv.cellEditMode = ObjectListView.CELLEDIT_SINGLECLICK 
     self.setTracks() 

     #Create Actions Object List 
     self.ActionsOlv = ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT|wx.SUNKEN_BORDER) 
     self.setActions() 

     # create source txt box - it stores values only, not displayed 
     self.txSource = wx.TextCtrl(self, wx.ID_ANY, name=u'txSource', value=u'') 
     # create dest txt box - it stores values only, not displayed 
     self.txDest = wx.TextCtrl(self, wx.ID_ANY, name=u'txDest', value=u'')   


     # create browse to source button 
     sourceBtn = wx.Button(self, wx.ID_ANY, "Browse Source") 
     sourceBtn.Bind(wx.EVT_BUTTON, self.onBrowseSource)   

     # create browse dest button 
     destBtn = wx.Button(self, wx.ID_ANY, "Browse Destination") 
     destBtn.Bind(wx.EVT_BUTTON, self.onBrowseDest) 

     # create Move Files button 
     moveBtn = wx.Button(self, wx.ID_ANY, "Move Files") 
     moveBtn.Bind(wx.EVT_BUTTON, self.onMoveFiles) 

     # create Save Changes button 
     saveChangesBtn = wx.Button(self, wx.ID_ANY, "Save Changes") 
     saveChangesBtn.Bind(wx.EVT_BUTTON, self.onSaveChanges) 

     # create Discard Changes button 
     discardChangesBtn = wx.Button(self, wx.ID_ANY, "Discard Changes") 
     discardChangesBtn.Bind(wx.EVT_BUTTON, self.onMoveFiles) 

     # print list button - debug only 
     printBtn = wx.Button(self, wx.ID_ANY, "Print List") 
     printBtn.Bind(wx.EVT_BUTTON, self.onPrintBtn) 

     # create check box to include all sub files 
     self.cbSubfolders = wx.CheckBox(self, wx.ID_ANY, 
       label=u'Include Subfolders', name=u'cbSubfolders', style=0) 
     self.cbSubfolders.SetValue(True) 
     self.cbSubfolders.Bind(wx.EVT_CHECKBOX, self.OnCbSubfoldersCheckbox) 

     # create check box to repace file names 
     self.cbReplaceFilename = wx.CheckBox(self, wx.ID_ANY, 
       label=u'Replace Filename with Title Tag', 
       name=u'cbReplaceFilename', style=0) 
     self.cbReplaceFilename.SetValue(False) 
     self.cbReplaceFilename.Bind(wx.EVT_CHECKBOX, self.OnCbReplaceFilenameCheckbox) 

     #Create a simple search 
     self.SearchSimple = wx.SearchCtrl(self) 

     # Create some sizers 
     mainSizer = wx.BoxSizer(wx.VERTICAL) 

     sub1MainSizer = wx.BoxSizer(wx.VERTICAL) 
     sub2MainSizer = wx.BoxSizer(wx.HORIZONTAL) 
     sub3MainSizer = wx.BoxSizer(wx.HORIZONTAL) 

     trackSizer = wx.StaticBoxSizer(self.stTracks, wx.VERTICAL) 
     eventSizer = wx.StaticBoxSizer(self.stEvents, wx.VERTICAL) 
     folderSizer = wx.StaticBoxSizer(self.stFolders, wx.HORIZONTAL) 
     optionsSizer = wx.StaticBoxSizer(self.stOptions, wx.VERTICAL) 
     actionsSizer = wx.StaticBoxSizer(self.stActions, wx.HORIZONTAL) 
     searchSizer = wx.StaticBoxSizer(self.stSearch, wx.HORIZONTAL) 

     #Add widgets to sizers 
     trackSizer.Add(self.TrackOlv, 1, wx.ALL|wx.EXPAND, 2) 
     eventSizer.Add(self.ActionsOlv, 1, wx.ALL|wx.EXPAND, 2) 

     folderSizer.Add(sourceBtn, 0, wx.ALL, 2)   
     folderSizer.Add(destBtn, 0, wx.ALL, 2) 

     optionsSizer.Add(self.cbSubfolders, 0, wx.ALL, 2) 
     optionsSizer.Add(self.cbReplaceFilename, 0, wx.ALL, 2) 

     actionsSizer.Add(printBtn, 0, wx.ALL, 2) 
     actionsSizer.Add(moveBtn, 0, wx.ALL, 2) 
     actionsSizer.Add(saveChangesBtn, 0, wx.ALL, 2) 
     actionsSizer.Add(discardChangesBtn, 0, wx.ALL, 2) 

     searchSizer.Add(self.SearchSimple, wx.ALL, 2) 

     #Add sizers to correct sub   
     sub1MainSizer.Add(trackSizer, 1 , wx.ALL|wx.EXPAND, 2) 
     sub1MainSizer.Add(eventSizer, 1 , wx.ALL|wx.EXPAND, 2) 

     sub2MainSizer.Add(folderSizer, 0, wx.ALL, 2) 
     sub2MainSizer.Add(optionsSizer, 0, wx.ALL, 2) 
     sub2MainSizer.Add(searchSizer, 0, wx.ALL, 2) 

     sub2MainSizer.Add(actionsSizer, 0, wx.ALL, 2) 

     #Add subs to main 
     mainSizer.Add(sub1MainSizer, 1, wx.ALL|wx.EXPAND, 2) 
     mainSizer.Add(sub2MainSizer, 1, wx.ALL, 2) 
     #mainSizer.Add(sub3MainSizer, 1, wx.ALL, 2) 

     self.SetSizer(mainSizer) 
     mainSizer.Fit(self) 

    #---------------------------------------------------------------------- 
    # Set the GUI column headers and width 
    #---------------------------------------------------------------------- 
    def setTracks(self, data=None): 
     self.TrackOlv.SetColumns([ 
      ColumnDefn("Title", "left", 100, "atrTitle"), 
      ColumnDefn("Artist", "left", 100, "atrArtist"), 
      ColumnDefn("Album", "left", 100, "atrAlbum"), 
      ColumnDefn("Source", "left", 300, "atrSource"), 
      ColumnDefn("Destination", "left", 300, "atrDest"), 
     ]) 

    def setActions(self, data=None): 
     self.ActionsOlv.SetColumns([ 
      ColumnDefn("Time", "left", 100, "timestamp"), 
      ColumnDefn("Action", "left", 450, "action"), 
      ColumnDefn("Result", "left", 450, "result") 
     ]) 

    #---------------------------------------------------------------------- 
    # GUI EVENTS 
    #----------------------------------------------------------------------- 

    #Select Source of files 
    def onBrowseSource(self, event): 
     print "OnBrowseSource"  
     source = selectFolder("Select the Source Directory") 

     print "--source :" + source 

     self.txSource.SetValue(source) 
     self.anEvent = Action(datetime.datetime.now(),source,"Set as Source dir") 
     self.ActionsOlv.AddObject(self.anEvent) 

     self.populateList() 

    #Select Source of files 
    def onBrowseDest(self, event): 
     print "OnBrowseDest"  
     dest = selectFolder("Select the Destination Directory") 

     print dest 

     self.txDest.SetValue(dest) 
     self.anEvent = Action(datetime.datetime.now(),dest,"Set as Destination dir") 
     self.ActionsOlv.AddObject(self.anEvent) 

     self.populateList() 

    def OnCbSubfoldersCheckbox(self, event): 
     print "cbSubfolder" 
     self.populateList()  

    def OnCbReplaceFilenameCheckbox(self, event): 
     print "cbReplaceFilename" 
     self.populateList() 

    def onMoveFiles(self, event): 
     print "onMoveFiles" 
     self.moveFiles() 

    def onSaveChanges(self, event): 
     print "onSaveChanges" 
     self.saveChanges() 

    def onDiscardChanges(self, event): 
     print "onDiscardChanges" 
     self.discardChanges() 


    def onPrintBtn(self, event): 
     print "onPrintBtn" 

     #Why does this work 
     #rowObj = self.dataOlv.GetSelectedObject() 
     #print rowObj.author 
     #print rowObj.title 

     #debug - how many item in the list... why does it only print 1? 
     itemcount = self.TrackOlv.GetItemCount()   
     print "-- itemcount: " + str(itemcount) 

     getData = self.TrackOlv.GetItemData(1) 
     print "-- getData: " + str(getData)  

     trackList = self.TrackOlv.GetObjects()   
     for tracks in trackList:   
      print tracks.atrTitle, tracks.atrArtist, tracks.atrAlbum, tracks.atrSource, tracks.atrDest 


    #------------- 
    #Computations 
    #------------- 

    def defineDestFilename(self, sFullDestPath): 
     print "define dest" 

     iCopyX = 0 
     bExists = False 
     sOrigName = sFullDestPath 

     #If the file does not exist return original path/filename 
     if os.path.isfile(sFullDestPath) == False: 
      print "-" + sFullDestPath + " is valid" 
      return sFullDestPath 

     #Add .copyX.mp3 to the end of the file and retest until a new filename is found 
     while bExists == False: 
      sFullDestPath = sOrigName 
      iCopyX += 1 
      sFullDestPath = sFullDestPath + ".copy" + str(iCopyX) + ".mp3" 
      if os.path.isfile(sFullDestPath) == False: 
       print "-" + sFullDestPath + " is valid" 
       self.lvActions.Append([datetime.datetime.now(),"Desitnation filename changed since file exists",sFullDestPath]) 
       bExists = True 

     #return path/filename.copyX.mp3 
     return sFullDestPath 


    def populateList(self): 
     print "populateList" 

     sSource = self.txSource.Value 
     sDest = self.txDest.Value 

     #Initalize list to reset all values on any option change 
     itemcount = self.TrackOlv.GetItemCount()   
     print "-- itemcount: " + str(itemcount) 
     if itemcount > 0: 
      self.TrackOlv.DeleteAllItems() 
      print "--list cleaned" 

     #Create list of files 
     if self.cbSubfolders.Value == True: 
      listOfFiles = getListRecursive(sSource) 
     else: 
      listOfFiles = getList(sSource)  

     print listOfFiles 

     #prompt if no files detected 
     if listOfFiles == []: 
      self.anEvent = Action(datetime.datetime.now(),"Parse Source for .MP3 files","No .MP3 files in source directory") 
      self.ActionsOlv.AddObject(self.anEvent) 

     #Populate list after both Source and Dest are chosen 
     if len(sDest) > 1 and len(sDest) > 1:  
      print "-iterate listOfFiles" 

      for file in listOfFiles: 

       #gest Source and Filename 
       (sSource,sFilename) = os.path.split(file) 
       print "-- source: " + sSource 
       print "-- filename: " + sFilename 

       #sFilename = os.path.basename(file) 
       sTitle = getTitle(file) 
       print "-- title: " + sTitle 

       #Get artist 
       try: 
        sArtist = getArtist(file) 
       except UnicodeDecodeError: 
        print "unicode" 
        sArtist = "unkown" 
       print "-- artist: " + sArtist 

       #Get Album 
       sAlbum = getAblum(file) 
       print "-- album: " + sAlbum 

       # Make dest path = sDest + Artist + Album 
       sDestDir = os.path.join (sDest, sArtist) 
       sDestDir = os.path.join (sDestDir, sAlbum) 

       #If file exists change destination to *.copyX.mp3 
       if self.cbReplaceFilename.Value == True: 
        sDestDir = self.defineDestFilename(os.path.join(sDestDir,sTitle)) 
       else: 
        sDestDir = self.defineDestFilename(os.path.join(sDestDir,sFilename)) 
       print "-- dest: " + sDestDir 

       # Populate listview with track info     
       self.aTrack = Track(sTitle,sArtist,sAlbum,sSource,sDestDir)   
       self.TrackOlv.AddObject(self.aTrack) 
       self.Update() 
       print self.aTrack.atrAlbum 


       print "** ITEM ADDED **" 
     else: 
      print "-list not iterated"   

    def saveChanges (self): 
     print "save Changes" 

    def discardChanges (self): 
     print "discard Changes" 

    def moveFiles (self): 
     print "move files" 

     #for track in self.TrackOlv: 
     # print "-iterate SourceDest" 
     # #create dir 
     # (sDest,filename) = os.path.split(self.TrackOlv) 
     # print "-check dest" 
     #  
     # if not os.path.exists(sDest): 
     #  print "-Created dest" 
     #  os.makedirs(sDest) 
     #  self.lvActions.Append([datetime.datetime.now(),sDest,"Created"]) 
     #  self.Update() 
     #  self.lvActions.EnsureVisible(self.lvActions.GetItemCount() -1) 
     # 
     # #Move File 
     # print "-move file" 
     # shutil.move(SourceDest[0],SourceDest[1]) 
     # self.lvActions.Append([datetime.datetime.now(),filename,"Moved"]) 
     # self.Update() 
     # self.lvActions.EnsureVisible(self.lvActions.GetItemCount() -1) 
     # 
     #self.lvActions.Append([datetime.datetime.now(),"Move Complete","Success"]) 
     #self.Update() 
     #self.lvActions.EnsureVisible(self.lvActions.GetItemCount() -1)  



######################################################################## 
class MainFrame(wx.Frame): 
    #---------------------------------------------------------------------- 
    def __init__(self): 
     wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, 
          title="MP3 Manager", size=(1024,768)) #W by H 
     panel = MainPanel(self) 

######################################################################## 
class GenApp(wx.App): 

    #---------------------------------------------------------------------- 
    def __init__(self, redirect=False, filename=None): 
     wx.App.__init__(self, redirect, filename) 

    #---------------------------------------------------------------------- 
    def OnInit(self): 
     # create frame here 
     frame = MainFrame() 
     frame.Show() 
     return True 

#---------------------------------------------------------------------- 
def main(): 
    """ 
    Run the demo 
    """ 
    app = GenApp() 
    app.MainLoop() 

if __name__ == "__main__": 
    main() 

回答

1

我发现了这个问题。在将sizer与按钮添加到主sizer的行中,我将比例标志设置为'1'。这一改变修复了它。

mainSizer.Add(sub2MainSizer, 0, wx.ALL, 2)