【趋势科技实习录】UI添加滚动条

应用需求:failcase出现的太多,导致在一个静态文本区不能完全显示出来。

知识搜索:前期考虑用Tk,实践发现这个模块和staicText是不兼用的,会出现两个界面;后来搜索到wx.ScrolledWindow,在wxPython中,滚动条不是框架本身的一个元素,而是被类wx.ScrolledWindow控制。你可以在任何你要使用wx.Panel的地方使用wx.ScrolledWindow,并且滚动条移动所有在滚动窗口中的项目

额外说一点就是TextCtrl,它有一个参数也是控制滚动条的。

最终效果图:

代码区(标注的地方是本人做的修改):

'''
Created on 2014-7-17

@author: penny_jin
'''
import wx
import wx.grid
import subprocess
import platform
import os
import sys
import shutil
import time
import re
from xml.etree import ElementTree
import glob
import logging
import tkMessageBox
from Tkinter import Tk

IsDLL = "--dll" 

class MainFrame(wx.Frame):
    def __init__(self, parent, ID, title):
        logging.info("Start DCERF Check Frame")
        wx.Frame.__init__(self,parent,ID,title,wx.DefaultPosition,wx.Size(750,750)) 
        
        # add scrollbar by xuan_qi     
        panel=wx.ScrolledWindow(self,-1)     
        panel.SetScrollbars(1,1,1500,1500) 
        
        self.btn0 = wx.Button(panel,-1,'Cancel',pos=(0,2),size=(50,22))
        self.Bind(wx.EVT_BUTTON, self.OnClickBtn0, self.btn0) 
        self.btn0.SetDefault() 
                        
    
        self.btn2 = wx.Button(panel,-1,'Run',(80,2))
        self.Bind(wx.EVT_BUTTON, self.OnClickBtn2, self.btn2) 
        self.btn2.SetDefault()
          
        self.btn3 = wx.Button(panel,-1,'RunAll',(160,2))
        self.Bind(wx.EVT_BUTTON, self.OnClickBtn3, self.btn3) 
        self.btn3.SetDefault()
        
        self.btn4 = wx.Button(panel,-1,'RunDebugMode2',(240,2))
        self.Bind(wx.EVT_BUTTON, self.OnClickBtn4, self.btn4) 
        self.btn4.SetDefault()
        
        self.btn5 = wx.Button(panel,-1,'OpenDCELog',(345,2))
        self.Bind(wx.EVT_BUTTON, self.OnClickBtn5, self.btn5) 
        self.btn5.SetDefault()
        
        
        samplelist = ['dll','exe']
        rx = wx.RadioBox(panel,-1,"Change Current TSC Version",(440,0),wx.DefaultSize,samplelist,1,wx.RA_SPECIFY_ROWS)
        self.Bind(wx.EVT_RADIOBOX, self.OnRadio, rx)
        
        
        self.btn1 = wx.Button(panel,-1,'RunRIDE',pos=(650,2))
        self.Bind(wx.EVT_BUTTON, self.OnClickBtn1, self.btn1) 
        self.btn1.SetDefault()
                        
                
        selectAll = wx.CheckBox(panel,-1,"",pos=(10,30),name='SelectedAll')
        self.Bind(wx.EVT_CHECKBOX, self.OnSelectedAll, selectAll)
        
        wx.StaticText(panel,-1,"CaseID",pos=(50,30))
        wx.StaticText(panel,-1,"FailReason",pos=(160,30))        
        
        
        #----- create fail case list table --------#
        ## get fail case count ##
        (self.fail_case_list,fail_case_reasons)  = self.getFailCaseStatus()
        if len(self.fail_case_list) == 0:
            logging.warning("get fail case count 0")
            Tk().withdraw()
            tkMessageBox.showinfo("Please Check", "No fail case found,please check by manual.")
            return
        else:
            logging.info("Fail case count %i" % len(self.fail_case_list))
        
        self.case_directory_info = self.get_case_directory(self.fail_case_list)
        
        i = 0
        self.cb_list = []
        for caseid in self.fail_case_list:            
            cb = wx.CheckBox(panel,-1,"",pos=(10,50+i*20),name=self.case_directory_info[caseid]) 
            wx.HyperlinkCtrl(panel,-1,caseid,url="", pos=(40,50+i*20))
            wx.StaticText(panel,-1,fail_case_reasons[caseid],pos=(150,50+i*20))
            self.Bind(wx.EVT_HYPERLINK, self.OnClickCaseID)            
            self.cb_list.append(cb)
            i+=1
        
    # cancel selected checkbox, and set them to disable    
    def OnClickBtn0(self,event):
        for cb in self.cb_list:
            cb.SetValue(False)
        
    
    # open RIDE for case content view #    
    def OnClickBtn1(self, event):   
        subprocess.Popen("python C:\\Python27\\Scripts\\ride.py",creationflags=subprocess.CREATE_NEW_CONSOLE)
        
    # Run multi or single case in new console#    
    def OnClickBtn2(self,event):
        #global IsDLL
        singleCmd = r"python C:\TestDCE\StartTest.py --pause %s --case=" %IsDLL
        for i, cb in enumerate(self.cb_list):
            if cb.GetValue():
                singleCmd += self.fail_case_list[i] + ','
        if ',' not in singleCmd:
            logging.warn("Not select case to run")
            return
        else:
            singleCmd = singleCmd[0:len(singleCmd)-1]
            logging.info("RunCaseCmd:%s" %singleCmd)
            #self.btn2.Disable()
            subprocess.Popen(singleCmd,creationflags=subprocess.CREATE_NEW_CONSOLE)
            #max wait process terminate time = 600s 10mins
            """
            x = 1
            while x < 300:
                if process.poll()== None:
                    time.sleep(2)
                    x+=1
                else:     
                    self.btn2.Enable()
                    break
            self.btn2.Enable()
            """
            """
            caselist = ''
            for line in process.stdout.readlines():
                m2 = re.match('(.*) :: .* | FAIL |$',line)
                if m2 is not None and m2.group(1) is not None:
                    caselist+=m2.group(1)
                    print m2.group(1)
                    print line
            if 0 != len(caselist):
                Tk().withdraw()
                tkMessageBox.showinfo("Case Fail!", caselist)
                return
            Tk().withdraw()
            tkMessageBox.showinfo("Pass!", singleCmd)
            """
            
    # Run all failed cases in new console#    
    def OnClickBtn3(self,event):
        commandLine = r"python C:\TestDCE\StartTest.py %s --pause --failcase=NewFailCase.xml" %IsDLL
        subprocess.Popen(commandLine,creationflags=subprocess.CREATE_NEW_CONSOLE)

    # Run only one case step by step(in debugmode=2)
    def OnClickBtn4(self,event):
        singleCmd = r"python C:\TestDCE\StartTest.py --pause %s --debug=2 --case=" %IsDLL
        for i, cb in enumerate(self.cb_list):
            if cb.GetValue():
                singleCmd += self.fail_case_list[i] + ','
                
        if ',' not in singleCmd:
            logging.error("Not select case to run")
            Tk().withdraw()
            tkMessageBox.showinfo("Error", "Not select case to run")
            return
        elif len(re.findall(',',singleCmd)) > 1:
            logging.error("Debug mode only support execute one case at one time")
            Tk().withdraw()
            tkMessageBox.showinfo("Error", "Debug mode only support run one case at one time")
            return
        else:
            singleCmd = singleCmd[0:len(singleCmd)-1]
            logging.info("RunCaseCmd:%s" %singleCmd)
            subprocess.Popen(singleCmd,creationflags=subprocess.CREATE_NEW_CONSOLE)
            
            
    # Open selected case dce debug log folder,only support open one log folder one time
    def OnClickBtn5(self,event):
        singleCmd = "explorer.exe c:\TestDCE\dcelogs\\"
        for i, cb in enumerate(self.cb_list):
            if cb.GetValue():
                singleCmd += self.fail_case_list[i] + ','
                
        if ',' not in singleCmd:
            logging.error("Not select case")
            wx.MessageBox("Not select case to open log")
            return
        elif len(re.findall(',',singleCmd)) > 1:
            logging.error("Only support Open one dcelog at one time")
            wx.MessageBox("Only support Open one dcelog at one time")           
            return
        else:
            singleCmd = singleCmd[0:len(singleCmd)-1]
            
        bitness = platform.machine()
        if '64' in bitness:
            singleCmd +='_X64'
                            
        logging.info(singleCmd)
        subprocess.call(singleCmd)        
            
        
    def OnRadio(self,event):
        global IsDLL
        text = event.GetEventObject().GetStringSelection()
        
        if 'dll' in text:
            IsDLL = '--dll'
        else:
            IsDLL = ''
        logging.info("Change tsc version to %s" %text)
     
    def OnSelectedAll(self,event):
        if event.GetEventObject().GetValue():
            logging.info("Select all fail case" )
            for i, cb in enumerate(self.cb_list):
                cb.SetValue(True)
              
            
    def OnClickCaseID(self,event):
        caseID = event.GetEventObject().GetLabel()
        #print '\n----  OnButton_FrameHandler() for %s', %(caseID.GetLabelText())
        commandline = r"explorer.exe c:\TestDCE\testcases\%s\"" %self.case_directory_info[caseID]
        logging.info(commandline)
        subprocess.call(commandline)
        
              
    def getFailCaseStatus(self):
        """get fail case count
         Get names of test cases from output.xml by status
         """
        file_names = glob.glob('C:\\TestDCE\\testlogs\\*.xml')
        if 0 == len(file_names):
            logging.ERROR("Can't find output file")
            return
        else:    
            file_path = file_names[0]
        if not os.access(file_path, os.F_OK):
            logging.warning('%s does not exist, maybe you are run normal case with rebootcase mode' % file_path)
        fail_case_list = []
        
        #case_directory_info={};
        
        cases_reason={}
        
        root = ElementTree.parse(file_path)
        test_case_list = root.getiterator('test')
        
        # execute case count
        
        #casecount = len(test_case_list)
         
        for test_case in test_case_list:
            if 'FAIL' == test_case.find('status').attrib['status']:
                fail_case_list.append(test_case.attrib['name'])
                #case_directory_info[test_case.attrib['name']]=test_case.get
                flag = 0
                messagelist = list(test_case.iter('msg'))
                for msg in messagelist:
                    if 'FAIL' == msg.attrib['level']:
                        #print test_case.attrib['name'] + '--------' +msg.text
                        cases_reason[test_case.attrib['name']]=msg.text
                        flag = 1
                        break
                ##may be setup or teardown failed
                if flag == 0:
                    statuslist = list(test_case.iter('status'))
                    for sts in statuslist:
                        if 'yes' == sts.get('critical'):
                            #print test_case.attrib['name'] + '--------' +sts.text
                            cases_reason[test_case.attrib['name']]=sts.text
                            break
                                     
        return (fail_case_list, cases_reason)   


    def get_case_directory(self,fail_case_list):
        test_command = ''
        for case_id in fail_case_list:
            test_command +='--test %s ' %case_id
        
        pybot_command = 'pybot '+ test_command +' --runmode DryRun --output NONE c:\\Testdce\\testcases'
        process = subprocess.Popen(pybot_command, shell=True,stdout=subprocess.PIPE)
        return_code = process.stdout.readlines()
        caseSuite = ""
        caseOperator = ""
        flag = 0
        case_directory_info={}
        
        for line in return_code:
            if flag ==2:
                flag =0
                continue
            if flag == 0:
                #m = re.match("(.*) :: .* | Pass |",line)
                m = re.match('Testcases\.(.*)\.(.*)\.(.*)',line)
                if m is not None:
                    if ':' in m.group(1) or '.' in m.group(1):
                        casepath = line.split('.')
                        caseSuite = casepath[1].replace(' ','_')
                        caseOperator = casepath[2].replace(' ','_')
                    else:
                        caseSuite = m.group(1).replace(' ','_')
                        caseOperator = m.group(2).replace(' ','_')
                    flag = 1
                    m = None
                continue
            if flag == 1:
                if "=======" in line:
                    continue
                if "------" in line:
                    continue
                
                m = re.match('(.*) :: .* | Pass |',line)
                if m is not None and m.group(1) is not None:
                        if '.' in m.group(1):
                            continue
                        case_directory_info[m.group(1)]= caseSuite + "\\" + caseOperator
                        logging.warning("%s >> %s" % (m.group(1),case_directory_info[m.group(1)]))
                else:
                        flag = 2       
        return case_directory_info 
     

              
    def OnCloseWindow(self, event):
        dial = wx.MessageDialog(None, 'Are you sure to quit?', 'QUIT?',
            wx.YES_NO | wx.NO_DEFAULT | wx.ICON_QUESTION)

        ret = dial.ShowModal()

        if ret == wx.ID_YES:
            self.Destroy()
        else:
            event.Veto()
        
        
class DiceApp(wx.App):
    def OnInit(self):
        frame = MainFrame(None, -1, "DCERF.py")
        frame.Show(True)
        self.SetTopWindow(frame)
        return True

    def OnCloseFrame(self, evt):
        evt.Skip()


def set_logger(logFileName):
    if os.path.exists(logFileName) and os.path.getsize(logFileName) > 30 * 1024 * 1024:
        index = 1
        while os.path.exists(logFileName + '.' + str(index)):
            index = index + 1
        #logfileName = logFile + '.' + str(index)
        shutil.move(logFileName, logFileName + '.' + str(index))
    
    logging.basicConfig(filename=logFileName, format='%(asctime)s %(levelname)-8s %(message)s', level=logging.DEBUG)
    #define a Handler which writes INFO messages or higher to the sys.stderr
    console = logging.StreamHandler()
    console.setLevel(logging.INFO)
    #set a format which is simpler for console use
    formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s')
    #tell the handler to use this format
    console.setFormatter(formatter)
    #add the handler to the root logger
    logging.getLogger('').addHandler(console) 


if __name__ == '__main__':
    set_logger('c:\TestDCE\DCERF_handle_result.log')
    app = DiceApp(False)
    app.MainLoop()


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值