在 GUI 中读取文件而不阻塞主线程

Reading a File without block main thead in GUI

在我的 中,我尝试过、失败过、学习过,并通过以下尝试回来了。

我有一个文本文件,其中的名称用逗号解析,如下所示:

Ann Marie,Smith,ams@companyname.com

列表中可能有 100 多个名字。我省略了生成所有其他 GUI 组件的代码,以专注于加载组合框和项目。

我试图在不阻塞主线程的情况下读取文本并将数据加载到组合框中。我查阅了一本教科书和Pythons文档,这是我想出的。

问题:

在我的 def read_employees(self,read_file): 中,我 return 我读取了 list 的数据。我知道 list 不是线程安全的,我在这里使用它的方式可以吗?

def textfilemanage(self): 中组合框的设置也是如此,我通过 self.combo = wx.ComboBox(self.panel, choices=data) 在该方法中设置了组合框。可以吗?

import wx
import concurrent.futures

class Mywin(wx.Frame):

    def __init__(self, parent, title):
        super(Mywin, self).__init__(parent, title=title, size=(300, 200))

        self.panel = wx.Panel(self)
        box = wx.BoxSizer(wx.VERTICAL)
        self.textfilemanage()
        self.label = wx.StaticText(self.panel, label="Your choice:", style=wx.ALIGN_CENTRE)
        box.Add(self.label, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 20)
        cblbl = wx.StaticText(self.panel, label="Combo box", style=wx.ALIGN_CENTRE)

        box.Add(cblbl, 0, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5)

        box.Add(self.combo, 1, wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 5)
        chlbl = wx.StaticText(self.panel, label="Choice control", style=wx.ALIGN_CENTRE)
        box.AddStretchSpacer()
        self.combo.Bind(wx.EVT_COMBOBOX, self.OnCombo)

        self.panel.SetSizer(box)
        self.Centre()
        self.Show()

    def read_employees(self,read_file):
        emp_list = []
        with open(read_file) as f_obj:
            for line in f_obj:
                emp_list.append(line)
        return emp_list

    def textfilemanage(self):
        filename = 'employees.txt'

        with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
            future_to_read = {executor.submit(self.read_employees, filename)}
            for future in concurrent.futures.as_completed(future_to_read):
                data = future.result()

        self.combo = wx.ComboBox(self.panel, choices=data)

    def OnCombo(self, event):
        self.label.SetLabel("You selected" + self.combo.GetValue() + " from Combobox")


app = wx.App()
Mywin(None, 'ComboBox and Choice demo')
app.MainLoop()

textfilemanage() 中的 for 循环会一直等到线程完成,因此不同的线程在代码中是无用的。

改为:

__init__ 中创建空组合框(布局需要)并将其分配给 self.combo

textfilemanage() 中启动线程但不要等待它。

read_employees() 中将最后的 return 语句替换为

wx.CallAfter(self.combo.Append, emp_list)

wx.CallAfter(self.combo.AppendItems, emp_list)

(这取决于接受哪​​个变体的wxPython版本)