def main(): app = wx.App(redirect=False) app.SetAppName(APPNAME) args, extra_args = MyArgumentParser().parse() LoggingConfiguration.set(args.log_level, args.log_filename, args.append) logging.debug('Arguments: {0!r}'.format(args)) logging.debug('Extra Arguments: {0!r}'.format(extra_args)) sys.stdout = open(CrossPlatform.get().user_config_path('stdout.log'), 'w') sys.stderr = open(CrossPlatform.get().user_config_path('stderr.log'), 'w') core = Core(args, extra_args) try: core.start() UiAdvanced(None, title="Desktop Mirror - " + VERSION, core=core) app.MainLoop() except KeyboardInterrupt: logging.info('^c') except: import traceback exc_type, exc_value, exc_traceback = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_traceback) logging.warn(''.join('!! ' + line for line in lines)) finally: core.stop() core.join(5)
def set(cls, log_level, log_filename, append): """ Configure a rotating file logging """ logger = logging.getLogger() logger.setLevel(logging.DEBUG) # Log to sys.stderr using log level passed through command line if log_level != logging.NOTSET: log_handler = logging.StreamHandler(sys.stdout) if sys.platform.find('linux') >= 0: formatter = ColoredFormatter(cls.COLOR_FORMAT) else: formatter = ColoredFormatter(cls.NO_COLOR_FORMAT, False) log_handler.setFormatter(formatter) log_handler.setLevel(log_level) logger.addHandler(log_handler) if CrossPlatform.get().is_windows(): log_filename = CrossPlatform.get().user_config_path('dm.log') # Log to rotating file using DEBUG log level log_handler = logging.handlers.RotatingFileHandler(log_filename, mode='a+', backupCount=3) formatter = logging.Formatter('%(asctime)s %(levelname)-8s ' '%(message)s') log_handler.setFormatter(formatter) log_handler.setLevel(logging.DEBUG) logger.addHandler(log_handler) if not append: # Create a new log file on every new # (i.e. not scheduled) invocation log_handler.doRollover()
def __init__(self, parent, id, title, callback=None): flag = wx.BORDER_NONE if CrossPlatform.get().is_linux(): flag = wx.RESIZE_BORDER wx.Frame.__init__(self, parent, id, title, style=flag | wx.STAY_ON_TOP | wx.FRAME_NO_TASKBAR | wx.CLIP_CHILDREN) self._callback = callback self.rootPanel = wx.Panel(self) self.rootPanel.SetBackgroundColour(wx.Colour(0, 0, 0)) centerPanel = wx.Panel(self.rootPanel) centerPanel.SetBackgroundColour(wx.Colour(0, 0, 0)) innerPanel = wx.Panel(centerPanel) innerPanel.SetBackgroundColour(wx.Colour(0, 0, 0)) rootBox = wx.BoxSizer(wx.HORIZONTAL) centerBox = wx.BoxSizer(wx.HORIZONTAL) innerBox = wx.BoxSizer(wx.VERTICAL) # I want this line visible in the CENTRE of the inner panel self.txt = wx.StaticText(innerPanel, label="") self.txt.SetFont(wx.Font(20, wx.MODERN, wx.NORMAL, wx.BOLD)) innerBox.Add(self.txt, 0, wx.ALL | wx.ALIGN_CENTER, border=0) innerPanel.SetSizer(innerBox) centerBox.Add(innerPanel, 1, wx.ALL | wx.ALIGN_CENTER, border=0) centerPanel.SetSizer(centerBox) rootBox.Add(centerPanel, 1, wx.ALL | wx.ALIGN_CENTER | wx.EXPAND, border=5) self.rootPanel.SetSizer(rootBox) rootBox.Fit(self) centerPanel.Bind(wx.EVT_LEFT_DOWN, self.OnMouseEvents) innerPanel.Bind(wx.EVT_LEFT_DOWN, self.OnMouseEvents) self.txt.Bind(wx.EVT_LEFT_DOWN, self.OnMouseEvents) self.Bind(wx.EVT_CLOSE, self.OnClose) self.timer = wx.Timer(self) self.Bind(wx.EVT_TIMER, self.OnTimer) self.timer.Start(40) # in miliseconds self.background_colour = 0 self.mouse_start_pos = None self.mouse_end_pos = None self.step = 0 self.dialog = HintDialog(self, -1) #self.dialog.Center() #self.dialog.SetTransparent(100) self.dialog.Show()
def ConfigSave(self): config = self.config for w in self._input: config.set('input', w, self._input[w].GetValue()) filepath = CrossPlatform.get().user_config_path('ui.ini') logging.info('Saving config to ' + filepath) with open(filepath, 'w') as configfile: config.write(configfile)
def prepare(self, args): # http://osdir.com/ml/python.py2exe/2006-01/msg00008.html # shlex has path problem on Windows 7 x86_64 # such as share/crtmpserver.lua -> sharecrtmpserver.lua params = [ CrossPlatform.get().share_path('crtmpserver.lua'), ] return ['crtmpserver'] + params
def __init__(self, args, extra_args): Thread.__init__(self) self._args = args self._extra_args = extra_args self._threads = [] self._event_handler = CoreEventHandler() if CrossPlatform.get().is_linux(): signal.signal(signal.SIGCHLD, self.signal_handler) signal.signal(signal.SIGTERM, self.signal_handler)
def signal_handler(self, signum, frame): logging.info('signal: ' + str(signum)) if signal.SIGTERM == signum: self.send_form_destroy() try: if CrossPlatform.get().is_linux(): if signal.SIGCHLD == signum: os.waitpid(-1, os.WNOHANG) except OSError: pass
def run(self, args): cmdline = self.prepare(args) logging.info(self._name + ' start: ' + ' '.join(cmdline)) if CrossPlatform.get().is_linux(): p = Popen(cmdline, stdout=PIPE, stderr=STDOUT) else: startupinfo = sb.STARTUPINFO() startupinfo.dwFlags |= sb.STARTF_USESHOWWINDOW startupinfo.wShowWindow = 0 p = Popen(cmdline, stdout=PIPE, stderr=STDOUT, startupinfo=startupinfo) self.p = p return self
def ConfigLoad(self): #filepath = CrossPlatform.get().user_config_path('ui.ini') #if not os.path.exists(filepath): filepath = CrossPlatform.get().system_config_path() logging.info('Loading config from ' + filepath) config = ConfigParser() config.read(filepath) if not config.has_section('input'): config.add_section('input') else: for w in self._input: if config.has_option('input', w): self._input[w].SetValue(config.get('input', w)) self.config = config
def OnStreamReceiver(self, data): if data[0] != StreamReceiver.EVENT_ASK_TO_PLAY: logging.warn('Unknown event: {}'.format(data)) return dlg = wx.MessageDialog(self, ('Stream Request. Accept?'), APPNAME, wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION) if dlg.ShowModal() == wx.ID_YES: if CrossPlatform.get().is_linux(): cmdline = ['ffplay', data[1]] Popen(cmdline) else: startupinfo = sb.STARTUPINFO() startupinfo.dwFlags |= sb.STARTF_USESHOWWINDOW startupinfo.wShowWindow = 0 cmdline = ['ffplay', data[1] + ' live=1'] Popen(cmdline, startupinfo=startupinfo)
def __init__(self, parent, title, core): super(UiAdvanced, self).__init__(parent, title=title, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE) self._core = core self._core.register_listener(self) self._input = dict() self.Bind(EVT_SOME_NEW_EVENT, self.handler) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) # ~/Downloads/png2ico/png2ico icon.ico # desktop-mirror-64.png desktop-mirror-32.png desktop-mirror-16.png self.SetIcon(wx.Icon(CrossPlatform.get().share_path('icon.ico'), wx.BITMAP_TYPE_ICO)) self.InitUI() self.ConfigLoad() self.OnClickFullScreen(None) self.Centre() self.Show()
def __init__(self, parent, title, core): super(UiAdvanced, self).__init__(parent, title=title, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE) self._core = core self._core.register_listener(self) self._input = dict() self.Bind(EVT_SOME_NEW_EVENT, self.handler) self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) # ~/Downloads/png2ico/png2ico icon.ico # desktop-mirror-64.png desktop-mirror-32.png desktop-mirror-16.png self.SetIcon( wx.Icon(CrossPlatform.get().share_path('icon.ico'), wx.BITMAP_TYPE_ICO)) self.InitUI() self.ConfigLoad() self.OnClickFullScreen(None) self.Centre() self.Show()
def prepare(self, args): # http://osdir.com/ml/python.py2exe/2006-01/msg00008.html # shlex has path problem on Windows 7 x86_64 # such as share/crtmpserver.lua -> sharecrtmpserver.lua params = [CrossPlatform.get().share_path('crtmpserver.lua'), ] return ['crtmpserver'] + params
def InitUI(self): def titleBox(hide=True): font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT) font.SetPointSize(16) hbox = wx.BoxSizer(wx.HORIZONTAL) text1 = wx.StaticText(panel, label="Desktop Mirror") text1.SetFont(font) hbox.Add(text1, flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=15) #hbox = wx.BoxSizer(wx.HORIZONTAL) #line = wx.StaticLine(panel) #hbox.Add(line, 1, flag=wx.EXPAND | wx.ALL, border=10) #vbox.Add(hbox, 1, wx.ALL, 5) if hide: map(lambda w: w.Hide(), [ w.GetWindow() for w in hbox.GetChildren() if w.GetWindow() is not None ]) return hbox def targetBox(): hbox = wx.BoxSizer(wx.HORIZONTAL) #hbox.Add(wx.StaticText(panel, label="Target"), # flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5) cb = wx.ComboBox(panel, 500, "127.0.0.1", style=wx.CB_DROPDOWN | wx.TE_PROCESS_ENTER) cb.SetMinSize((250, 0)) button1 = wx.Button(panel, label="Streaming") hbox.Add(cb, 1, flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border=0) hbox.Add(button1, 0, flag=wx.EXPAND | wx.LEFT | wx.ALIGN_RIGHT, border=5) self._input['address'] = cb self._input_stream = button1 self.Bind(wx.EVT_COMBOBOX, self.OnTargetChosen, cb) self.Bind(wx.EVT_TEXT, self.OnTargetKey, cb) self.Bind(wx.EVT_TEXT_ENTER, self.OnTargetKeyEnter, cb) self.Bind(wx.EVT_BUTTON, self.OnClickStream, button1) return hbox def geometryBox(hide=True): sb = wx.StaticBox(panel, label="Geometry") boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL) hbox = wx.BoxSizer(wx.HORIZONTAL) tc1 = wx.TextCtrl(panel) tc2 = wx.TextCtrl(panel) tc3 = wx.TextCtrl(panel) tc4 = wx.TextCtrl(panel) self._input['x'] = tc1 self._input['y'] = tc2 self._input['w'] = tc3 self._input['h'] = tc4 hbox.Add(wx.StaticText(panel, label="X"), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5) hbox.AddSpacer(5) hbox.Add(tc1, 1, flag=wx.EXPAND) hbox.AddSpacer(10) hbox.Add(wx.StaticText(panel, label="Y"), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5) hbox.AddSpacer(5) hbox.Add(tc2, 1, flag=wx.EXPAND) hbox.AddSpacer(10) hbox.Add(wx.StaticText(panel, label="W"), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5) hbox.AddSpacer(5) hbox.Add(tc3, 1, flag=wx.EXPAND) hbox.AddSpacer(10) hbox.Add(wx.StaticText(panel, label="H"), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5) hbox.AddSpacer(5) hbox.Add(tc4, 1, flag=wx.EXPAND) boxsizer.Add(hbox, flag=wx.LEFT | wx.TOP | wx.EXPAND, border=5) hbox2 = wx.BoxSizer(wx.HORIZONTAL) button1 = wx.Button(panel, label="Select Area") hbox2.Add(button1, 1, flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border=15) button2 = wx.Button(panel, label="Full Screen") hbox2.Add(button2, 1, flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border=15) boxsizer.Add(hbox2, flag=wx.LEFT | wx.TOP | wx.EXPAND, border=5) self.Bind(wx.EVT_BUTTON, self.OnClickSelectionArea, button1) self.Bind(wx.EVT_BUTTON, self.OnClickFullScreen, button2) if hide: map(lambda w: w.Hide(), [ w.GetWindow() for w in hbox.GetChildren() if w.GetWindow() is not None ]) map(lambda w: w.Hide(), [ w.GetWindow() for w in hbox2.GetChildren() if w.GetWindow() is not None ]) sb.Hide() return boxsizer def videoBox(hide=True): sb = wx.StaticBox(panel, label="Video") boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL) fgs = wx.FlexGridSizer(3, 2, 5, 25) tc1 = wx.TextCtrl(panel) tc2 = wx.TextCtrl(panel) self._input['video_input'] = tc1 self._input['video_output'] = tc2 fgs.AddMany([(wx.StaticText(panel, label="input")), (tc1, 1, wx.EXPAND), (wx.StaticText(panel, label="output")), (tc2, 1, wx.EXPAND)]) fgs.AddGrowableCol(1, 1) boxsizer.Add(fgs, flag=wx.LEFT | wx.TOP | wx.EXPAND, border=5) if hide: map(lambda w: w.Hide(), [ w.GetWindow() for w in fgs.GetChildren() if w.GetWindow() is not None ]) sb.Hide() return boxsizer def audioBox(hide=True): sb = wx.StaticBox(panel, label="Audio") boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL) fgs = wx.FlexGridSizer(3, 2, 5, 25) tc1 = wx.TextCtrl(panel) tc2 = wx.TextCtrl(panel) self._input['audio_input'] = tc1 self._input['audio_output'] = tc2 fgs.AddMany([(wx.StaticText(panel, label="input")), (tc1, 1, wx.EXPAND), (wx.StaticText(panel, label="output")), (tc2, 1, wx.EXPAND)]) fgs.AddGrowableCol(1, 1) boxsizer.Add(fgs, flag=wx.LEFT | wx.TOP | wx.EXPAND, border=5) if hide: map(lambda w: w.Hide(), [ w.GetWindow() for w in fgs.GetChildren() if w.GetWindow() is not None ]) sb.Hide() return boxsizer def fullareaBox(hide=True): hbox = wx.BoxSizer(wx.HORIZONTAL) rb1 = wx.RadioButton(panel, -1, 'Fullscreen', style=wx.RB_GROUP) hbox.Add(rb1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5) rb2 = wx.RadioButton(panel, -1, 'Area') hbox.Add(rb2, 1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5) self._input_rb_fullscreen = rb1 self._input_rb_area = rb2 self.Bind(wx.EVT_RADIOBUTTON, self.OnClickFullArea, id=rb1.GetId()) self.Bind(wx.EVT_RADIOBUTTON, self.OnClickFullArea, id=rb2.GetId()) return hbox panel = wx.Panel(self, -1) hbox = wx.BoxSizer(wx.HORIZONTAL) vboxL = wx.BoxSizer(wx.VERTICAL) vboxR = wx.BoxSizer(wx.VERTICAL) png = wx.Image(CrossPlatform.get().share_path('desktop-mirror-64.png'), wx.BITMAP_TYPE_ANY).ConvertToBitmap() image = wx.StaticBitmap(panel, -1, png, (0, 0), (png.GetWidth(), png.GetHeight())) vboxL.Add(image) flags = wx.EXPAND #vboxR.Add(titleBox(), 0, wx.ALL, 0) vboxR.Add(targetBox(), 1, flag=flags | wx.TOP, border=10) vboxR.Add(fullareaBox(), 0, flag=flags, border=10) for fn in (titleBox, geometryBox, videoBox, audioBox): fn() #vboxR.Add(fn(), 0, flag=flags, border=10) hbox.Add(vboxL, 0, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 10) hbox.Add(vboxR, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 10) #self.statusbar = self.CreateStatusBar() panel.SetAutoLayout(True) panel.SetSizer(hbox) panel.Layout() panel.Fit() self.Fit()
def InitUI(self): def titleBox(hide=True): font = wx.SystemSettings_GetFont(wx.SYS_SYSTEM_FONT) font.SetPointSize(16) hbox = wx.BoxSizer(wx.HORIZONTAL) text1 = wx.StaticText(panel, label="Desktop Mirror") text1.SetFont(font) hbox.Add(text1, flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=15) #hbox = wx.BoxSizer(wx.HORIZONTAL) #line = wx.StaticLine(panel) #hbox.Add(line, 1, flag=wx.EXPAND | wx.ALL, border=10) #vbox.Add(hbox, 1, wx.ALL, 5) if hide: map(lambda w: w.Hide(), [w.GetWindow() for w in hbox.GetChildren() if w.GetWindow() is not None]) return hbox def targetBox(): hbox = wx.BoxSizer(wx.HORIZONTAL) #hbox.Add(wx.StaticText(panel, label="Target"), # flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5) cb = wx.ComboBox(panel, 500, "127.0.0.1", style=wx.CB_DROPDOWN | wx.TE_PROCESS_ENTER ) cb.SetMinSize((250, 0)) button1 = wx.Button(panel, label="Streaming") hbox.Add(cb, 1, flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border=0) hbox.Add(button1, 0, flag=wx.EXPAND | wx.LEFT | wx.ALIGN_RIGHT, border=5) self._input['address'] = cb self._input_stream = button1 self.Bind(wx.EVT_COMBOBOX, self.OnTargetChosen, cb) self.Bind(wx.EVT_TEXT, self.OnTargetKey, cb) self.Bind(wx.EVT_TEXT_ENTER, self.OnTargetKeyEnter, cb) self.Bind(wx.EVT_BUTTON, self.OnClickStream, button1) return hbox def geometryBox(hide=True): sb = wx.StaticBox(panel, label="Geometry") boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL) hbox = wx.BoxSizer(wx.HORIZONTAL) tc1 = wx.TextCtrl(panel) tc2 = wx.TextCtrl(panel) tc3 = wx.TextCtrl(panel) tc4 = wx.TextCtrl(panel) self._input['x'] = tc1 self._input['y'] = tc2 self._input['w'] = tc3 self._input['h'] = tc4 hbox.Add(wx.StaticText(panel, label="X"), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5) hbox.AddSpacer(5) hbox.Add(tc1, 1, flag=wx.EXPAND) hbox.AddSpacer(10) hbox.Add(wx.StaticText(panel, label="Y"), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5) hbox.AddSpacer(5) hbox.Add(tc2, 1, flag=wx.EXPAND) hbox.AddSpacer(10) hbox.Add(wx.StaticText(panel, label="W"), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5) hbox.AddSpacer(5) hbox.Add(tc3, 1, flag=wx.EXPAND) hbox.AddSpacer(10) hbox.Add(wx.StaticText(panel, label="H"), flag=wx.TOP | wx.LEFT | wx.BOTTOM, border=5) hbox.AddSpacer(5) hbox.Add(tc4, 1, flag=wx.EXPAND) boxsizer.Add(hbox, flag=wx.LEFT | wx.TOP | wx.EXPAND, border=5) hbox2 = wx.BoxSizer(wx.HORIZONTAL) button1 = wx.Button(panel, label="Select Area") hbox2.Add(button1, 1, flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border=15) button2 = wx.Button(panel, label="Full Screen") hbox2.Add(button2, 1, flag=wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT, border=15) boxsizer.Add(hbox2, flag=wx.LEFT | wx.TOP | wx.EXPAND, border=5) self.Bind(wx.EVT_BUTTON, self.OnClickSelectionArea, button1) self.Bind(wx.EVT_BUTTON, self.OnClickFullScreen, button2) if hide: map(lambda w: w.Hide(), [w.GetWindow() for w in hbox.GetChildren() if w.GetWindow() is not None]) map(lambda w: w.Hide(), [w.GetWindow() for w in hbox2.GetChildren() if w.GetWindow() is not None]) sb.Hide() return boxsizer def videoBox(hide=True): sb = wx.StaticBox(panel, label="Video") boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL) fgs = wx.FlexGridSizer(3, 2, 5, 25) tc1 = wx.TextCtrl(panel) tc2 = wx.TextCtrl(panel) self._input['video_input'] = tc1 self._input['video_output'] = tc2 fgs.AddMany([(wx.StaticText(panel, label="input")), (tc1, 1, wx.EXPAND), (wx.StaticText(panel, label="output")), (tc2, 1, wx.EXPAND)]) fgs.AddGrowableCol(1, 1) boxsizer.Add(fgs, flag=wx.LEFT | wx.TOP | wx.EXPAND, border=5) if hide: map(lambda w: w.Hide(), [w.GetWindow() for w in fgs.GetChildren() if w.GetWindow() is not None]) sb.Hide() return boxsizer def audioBox(hide=True): sb = wx.StaticBox(panel, label="Audio") boxsizer = wx.StaticBoxSizer(sb, wx.VERTICAL) fgs = wx.FlexGridSizer(3, 2, 5, 25) tc1 = wx.TextCtrl(panel) tc2 = wx.TextCtrl(panel) self._input['audio_input'] = tc1 self._input['audio_output'] = tc2 fgs.AddMany([(wx.StaticText(panel, label="input")), (tc1, 1, wx.EXPAND), (wx.StaticText(panel, label="output")), (tc2, 1, wx.EXPAND)]) fgs.AddGrowableCol(1, 1) boxsizer.Add(fgs, flag=wx.LEFT | wx.TOP | wx.EXPAND, border=5) if hide: map(lambda w: w.Hide(), [w.GetWindow() for w in fgs.GetChildren() if w.GetWindow() is not None]) sb.Hide() return boxsizer def fullareaBox(hide=True): hbox = wx.BoxSizer(wx.HORIZONTAL) rb1 = wx.RadioButton(panel, -1, 'Fullscreen', style=wx.RB_GROUP) hbox.Add(rb1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5) rb2 = wx.RadioButton(panel, -1, 'Area') hbox.Add(rb2, 1, flag=wx.ALL | wx.ALIGN_CENTER_VERTICAL, border=5) self._input_rb_fullscreen = rb1 self._input_rb_area = rb2 self.Bind(wx.EVT_RADIOBUTTON, self.OnClickFullArea, id=rb1.GetId()) self.Bind(wx.EVT_RADIOBUTTON, self.OnClickFullArea, id=rb2.GetId()) return hbox panel = wx.Panel(self, -1) hbox = wx.BoxSizer(wx.HORIZONTAL) vboxL = wx.BoxSizer(wx.VERTICAL) vboxR = wx.BoxSizer(wx.VERTICAL) png = wx.Image(CrossPlatform.get().share_path('desktop-mirror-64.png'), wx.BITMAP_TYPE_ANY).ConvertToBitmap() image = wx.StaticBitmap(panel, -1, png, (0, 0), (png.GetWidth(), png.GetHeight())) vboxL.Add(image) flags = wx.EXPAND #vboxR.Add(titleBox(), 0, wx.ALL, 0) vboxR.Add(targetBox(), 1, flag=flags | wx.TOP, border=10) vboxR.Add(fullareaBox(), 0, flag=flags, border=10) for fn in (titleBox, geometryBox, videoBox, audioBox): fn() #vboxR.Add(fn(), 0, flag=flags, border=10) hbox.Add(vboxL, 0, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 10) hbox.Add(vboxR, 1, wx.ALL | wx.EXPAND | wx.ALIGN_CENTER, 10) #self.statusbar = self.CreateStatusBar() panel.SetAutoLayout(True) panel.SetSizer(hbox) panel.Layout() panel.Fit() self.Fit()