[Python] wxPython - wx.TextCtrl not updated inside a for loop (instead the program goes in...

Discussão em 'Python' iniciado por Stack, Dezembro 20, 2024.

  1. Stack

    Stack Membro Participativo

    This is the code. The code create a simple UI with drag and dropping for 2 excel ".xlsx" files (Origin file and Destination file). Then it will take the fields and all the values on their respective row and populate the destination file.

    The problem is the function:

    __set_datas()


    Inside the class:

    ParseExcelFieldsPanel


    If I print the results instead of updating the TextCtrl I can see all the fields, but the TextCtrl instead of being update at every cycle of the for loop, gets updated when the loop finished.

    This is my code:

    import wx
    import os
    import sys
    import openpyxl
    from threading import Thread

    mOriginExcelFilename = None
    mDestinationExcelFilename = None
    mOriginExcel = None
    mDestinationExcel = None

    class Data(object):
    mField = None
    mHeader = None
    mCell = None

    def __str__(self):
    return str(self.mField) + " " + str(self.mHeader) + " " + str(self.mCell)

    class WxUtils(object):

    def set_font_size(label, size):
    font = label.GetFont()
    font.SetPointSize(size)
    label.SetFont(font)

    def set_font_bold(label):
    font = label.GetFont()
    font.SetWeight(wx.FONTWEIGHT_BOLD)
    label.SetFont(font)

    def set_font_size_and_bold(label, size):
    font = label.GetFont()
    font.SetPointSize(size)
    font.SetWeight(wx.FONTWEIGHT_BOLD)
    label.SetFont(font)

    def set_font_size_and_bold_and_roman(label, size):
    font = label.GetFont()
    font.SetPointSize(size)
    font.SetWeight(wx.FONTWEIGHT_BOLD)
    font.SetFamily(wx.ROMAN)
    label.SetFont(font)

    class ParseExcelFieldsPanel(wx.Panel):

    __mtcResults = None

    def __init__(self, parent):
    wx.Panel.__init__(self, parent = parent)
    self.__init_layout()

    def __init_layout(self):
    main = wx.BoxSizer(wx.HORIZONTAL)
    main.AddSpacer(15)

    vbs = wx.BoxSizer(wx.VERTICAL)
    vbs.AddSpacer(15)

    vbs.Add(wx.StaticText(self, label = "Parsing Process:"), 0, wx.EXPAND)
    vbs.AddSpacer(5)
    self.__mtcResults = wx.TextCtrl(self, size = (self.GetParent().GetSize()[0] - 150, self.GetParent().GetSize()[1] - 250), style = wx.TE_MULTILINE | wx.TE_READONLY)
    vbs.Add(self.__mtcResults, 0, wx.EXPAND)
    vbs.AddSpacer(15)


    sub = wx.BoxSizer(wx.HORIZONTAL)
    bExit = wx.Button(self, wx.ID_ANY, "Exit")
    bExit.Bind(wx.EVT_BUTTON, self.__clicked_close)
    bParse = wx.Button(self, wx.ID_ANY, "Parse")
    bParse.Bind(wx.EVT_BUTTON, self.__clicked_parse)
    sub.AddSpacer(15)
    sub.Add(bExit, 1, wx.EXPAND | wx.ALL)
    sub.AddSpacer(15)
    sub.Add(bParse, 1, wx.EXPAND | wx.ALL)
    sub.AddSpacer(15)
    vbs.Add(sub, 0, wx.EXPAND | wx.ALL)
    main.Add(vbs, 0, wx.EXPAND | wx.ALL)

    self.SetSizer(main)
    self.Fit()
    self.Update()
    self.Layout()

    #region - Event Handler Methods
    def __clicked_close(self, evt):
    sys.exit()

    def __clicked_parse(self, evt):
    datasOrigin = self.__get_data_origin_excel()
    datasDestination = self.__get_data_destination_excel()
    self.__set_datas(datasOrigin, datasDestination)

    #endregion

    #region - Private Methods
    def __set_datas(self, datasOrigin, datasDestination):
    global mDestinationExcel
    global mDestinationExcelFilename

    count = 0
    field = None
    for dataO in datasOrigin:
    if field is None or dataO.mField != field:
    field = dataO.mField
    count += 1
    self.__mtcResults.AppendText("[{}] Extracting Field: {}\n".format(str(count), str(field)))
    for dataD in datasDestination:
    if dataO.mField == dataD.mField and dataO.mHeader == dataD.mHeader:
    if type(dataO.mCell.value) is float:
    dataD.mCell.value = round(dataO.mCell.value, 2)
    else:
    dataD.mCell.value = dataO.mCell.value
    mDestinationExcel.save(mDestinationExcelFilename)

    def __get_data_destination_excel(self):
    global mDestinationExcel

    datas = []
    found = False
    headers = [None]
    fyRow = None
    fy = None
    countQ = 0
    startFields = False
    for sheet in mDestinationExcel.sheetnames:
    foundSurpriseAnalysis = False
    for row in mDestinationExcel[sheet].iter_rows():
    for cr in row:
    if cr.row == 1:
    fyRow = row
    continue

    if cr.row == 2 and cr.column >= 2:
    if fyRow[cr.column - 1].value != "consensus.vaactuals":
    if fy is None or type(fyRow[cr.column - 1].value) is str:
    if fyRow[cr.column - 1].value != "Expectations" and fyRow[cr.column - 1].value != "Source Counts":
    fy = fyRow[cr.column - 1].value[:2] + "-20" + fyRow[cr.column - 1].value[2:]
    elif fyRow[cr.column - 1].value == "Expectations":
    fy = "E"
    else:
    fy = "S"
    else:
    fy = fyRow[cr.column - 1].value

    if fy != "consensus.vaactuals":
    if cr.value is not None and len(cr.value) > 0:
    if fy != "E" and fy != "S":
    if cr.value[:2] == "FY":
    headers.append(fy)
    else:
    headers.append(cr.value[:2] + fy)
    else:
    if fy == "E":
    if "Q" in cr.value:
    headers.append(cr.value[:2] + "FY-20" + cr.value[2:] + fy)
    else:
    headers.append(cr.value[:2] + "-20" + cr.value[2:] + fy)
    else:
    headers.append(cr.value + fy)
    else:
    headers.append(None)

    if len(headers) > 1 and type(row[0].value) is str and startFields == False:
    startFields = True

    if startFields:
    for cr in row:
    if foundSurpriseAnalysis:
    break
    if cr.column > 1 and cr.column < len(headers):
    data = Data()
    data.mField = row[0].value
    if data.mField == "Surprise Analysis % ":
    foundSurpriseAnalysis = True
    break
    data.mHeader = headers[cr.column - 1]
    data.mCell = cr
    datas.append(data)
    return datas


    def __get_data_origin_excel(self):
    global mOriginExcel

    datas = []
    found = False
    nColumn = 0
    mRowHeaders = []
    mRowsLetters = []
    fy = None
    crBefore = None
    for sheet in mOriginExcel.sheetnames:
    for row in mOriginExcel[sheet].iter_rows():
    for cr in row:
    if cr.value == "Line Item":
    nColumn = cr.column
    for r in mOriginExcel[sheet].iter_rows():
    for ccr in r:
    if ccr.row == cr.row - 1 and ccr.column >= cr.column:
    mRowsLetters.append(ccr.value)

    if ccr.row == cr.row - 2 and ccr.column >= cr.column + 2 and type(cr.value) is str:
    mRowHeaders.append(ccr.value)
    if mRowsLetters is not None and len(mRowsLetters) > 0:
    break
    break
    headers = []
    for i in range(0, nColumn + 1):
    headers.append(None)
    headers = headers + mRowHeaders

    letters = []
    for i in range(0, nColumn + 1):
    letters.append(None)
    for letter in mRowsLetters:
    if letter is not None:
    letters.append(letter)

    for i in range(nColumn, len(headers)):
    if i < len(row):
    cr = row
    if cr.value is not None and (type(cr.value) is int or type(cr.value) is float or cr.value == "-"):
    data = Data()
    data.mField = row[nColumn - 1].value
    data.mHeader = headers[cr.column - 1]
    if letters[cr.column - 1] == "E":
    data.mHeader += "E"
    data.mCell = cr
    datas.append(data)
    else:
    break
    return datas
    #endregion

    class MyFileDropTarget(wx.FileDropTarget):

    __mTextCtrl = None
    __mTxt = None

    def __init__(self, textCtrl, txt):
    wx.FileDropTarget.__init__(self)
    self.__mTextCtrl = textCtrl
    self.__mTxt = txt

    def OnDropFiles(self, x, y, filenames):
    global mOriginExcelFilename
    global mOriginExcel
    global mDestinationExcelFilename
    global mDestinationExcel

    for filepath in filenames:
    self.__mTextCtrl.SetValue("[+] Filepath:\n{}\n\n[+] {} Filename:\t{}\n\n".format(filepath, self.__mTxt, filepath[filepath.rfind("/") + 1 : ]))

    if self.__mTxt == "Origin":
    mOriginExcelFilename = filepath
    print(filepath)
    mOriginExcel = openpyxl.load_workbook(filepath, data_only = True)
    else:
    mDestinationExcelFilename = filepath
    mDestinationExcel = openpyxl.load_workbook(filepath, data_only = True, read_only = False)

    class GetFilesPanel(wx.Panel):

    __mtcOriginFile = None
    __mtcDestinationFile = None

    def __init__(self, parent):
    wx.Panel.__init__(self, parent = parent)
    self.__init_layout()

    #region - Private Methods
    def __init_layout(self):
    main = wx.BoxSizer(wx.VERTICAL)
    main.AddSpacer(15)

    sub = wx.BoxSizer(wx.HORIZONTAL)
    sub.AddSpacer(15)
    st = wx.StaticText(self, label = "Drag and Drop Origin and Destination Files")
    WxUtils.set_font_size_and_bold_and_roman(st, 15)
    sub.Add(st, 0, wx.EXPAND)
    main.Add(sub, 0, wx.EXPAND)
    main.AddSpacer(15)

    sub = wx.BoxSizer(wx.HORIZONTAL)
    sub.AddSpacer(15)
    vbs = wx.BoxSizer(wx.VERTICAL)
    st = wx.StaticText(self, label = "Drag Origin File Here:")
    self.__mtcOriginFile = wx.TextCtrl(self, style = wx.TE_MULTILINE | wx.TE_READONLY)
    self.__mtcOriginFile.SetDropTarget(MyFileDropTarget(self.__mtcOriginFile, "Origin"))
    vbs.Add(st, 0, wx.ALL)
    vbs.AddSpacer(5)
    vbs.Add(self.__mtcOriginFile, 1, wx.EXPAND | wx.ALL)
    sub.Add(vbs, 1, wx.EXPAND)

    sub.AddSpacer(15)

    vbs = wx.BoxSizer(wx.VERTICAL)
    st = wx.StaticText(self, label = "Drag Destination File Here:")
    self.__mtcDestinationFile = wx.TextCtrl(self, style = wx.TE_MULTILINE | wx.TE_READONLY)
    self.__mtcDestinationFile.SetDropTarget(MyFileDropTarget(self.__mtcDestinationFile, "Destination"))
    vbs.Add(st, 0, wx.ALL)
    vbs.AddSpacer(5)
    vbs.Add(self.__mtcDestinationFile, 1, wx.EXPAND|wx.ALL)
    sub.Add(vbs, 1, wx.EXPAND)
    sub.AddSpacer(15)
    main.Add(sub, 1, wx.EXPAND)

    main.AddSpacer(15)

    sub = wx.BoxSizer(wx.HORIZONTAL)
    bAbort = wx.Button(self, wx.ID_ANY, "Abort")
    bAbort.Bind(wx.EVT_BUTTON, self.clicked_abort)
    bContinue = wx.Button(self, wx.ID_ANY, "Continue")
    bContinue.Bind(wx.EVT_BUTTON, self.clicked_continue)
    sub.AddSpacer(15)
    sub.Add(bAbort, 1, wx.EXPAND | wx.ALL)
    sub.AddSpacer(15)
    sub.Add(bContinue, 1, wx.EXPAND | wx.ALL)
    sub.AddSpacer(15)
    main.Add(sub, 0, wx.EXPAND | wx.ALL)

    main.AddSpacer(15)
    self.SetSizer(main)
    self.Fit()
    #endregion

    #region - Events Handlers Methods
    def clicked_abort(self, evt):
    sys.exit()

    def clicked_continue(self, evt):
    global mOriginExcelFilename
    global mDestinationExcelFilename

    # if mOriginExcelFilename is not None and mDestinationExcelFilename is not None:
    self.GetParent().goto_choose_fields_excel_panel()

    #endregion

    class MainFrame(wx.Frame):

    __mMainPanel = None
    __mParseFieldsExcelPanel = None

    def __init__(self, title):
    wx.Frame.__init__(self, None, wx.ID_ANY, title, size = (1000, 500))
    wx.Frame.CenterOnScreen(self)
    self.__init_main_panel()

    def __init_main_panel(self):
    self.__mMainPanel = GetFilesPanel(self)
    self.__mMainPanel.Show()

    def __remove_main_panel(self):
    if self.__mMainPanel:
    self.__mMainPanel.Destroy()

    def goto_choose_fields_excel_panel(self):
    self.__remove_main_panel()
    self.__mParseFieldsExcelPanel = ParseExcelFieldsPanel(self)
    self.__mParseFieldsExcelPanel.Show()

    class MainApplication(wx.App):

    __mMainFrame: MainFrame = None

    def __init__(self, redirect):
    wx.App.__init__(self, redirect)

    def OnInit(self):
    self.__mMainFrame = MainFrame("Excel Automation Badhri")
    self.__mMainFrame.Show()
    self.SetTopWindow(self.__mMainFrame)
    return True

    def OnExit(self):
    return 0

    def main():
    application = MainApplication(False)
    application.MainLoop()


    if __name__ == "__main__":
    main()


    If I print the field on console I get them right. Also the TextCtrl get uploaded after the function as ended. Can someone tell me how to update the TextCtrl with the field being elaborated for every loop cycle? Thanks!

    [Please refrain from replying by writing unnecessary comments]

    Continue reading...

Compartilhe esta Página