как стабилизировать скорость моего wx.Gauge - PullRequest
0 голосов
/ 25 сентября 2019

скорость моего датчика изменяется в соответствии с инструкциями нити, которая работает с ним.когда инструкции просты, мой датчик работает очень быстро, но когда необходимо прочитать файл, мой датчик работает очень медленно.Я хочу стабилизировать это в том же темпе.Еще хуже, когда вам нужно извлечь текст из файла изображения, индикатор падает.и установить GUI

wx.Gauge(self, -1, 20, pos=(150, 300), size=(250, 25), style = wx.GA_HORIZONTAL)

Я уже изменил Range с большим значением (now Range=20), но ничего

Ответы [ 3 ]

1 голос
/ 26 сентября 2019

Ваш пример не включал ничего, что показывало бы, как вы читали файлы, но я предполагаю, основываясь на описании вашей проблемы, что они были вызваны из основного потока.Существует множество примеров того, как и зачем вам нужно запускать функции блокировки из другого потока, чтобы поддерживать отзывчивость пользовательского интерфейса.Если вы запускаете функцию из основного потока, она блокирует цикл обработки событий, что означает, что ни одно из ваших обычных событий (например, EVT_TIMER) не будет вызвано, пока функция не завершится.Вот ваш пример с имитируемой долгосрочной задачей в собственном потоке.

import time
import datetime
import wx
import threading


class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.Bind(wx.EVT_TIMER, self.OnTimer)
        self.gspeed = 20
        self.timer = wx.Timer(self)
        self.timer.Start(self.gspeed)

        self.star = True
        self.start_time = time.time()
        self.thread = None

        self.InitUI()
        self.start_long_running_task()


    def start_long_running_task(self):
        """
        :return: starts the long running task in its own thread to keep the UI responsive
        :rtype:
        """
        self.thread = threading.Thread(target=self.long_running_task)
        self.thread.start()

    def long_running_task(self):
        """
        :return:  simulated long running task
        :rtype:
        """
        print("long running task has started")
        # checks if the window has been closed and if the timer is still running
        while bool(self) and self.timer.IsRunning():
            # do something
            time.sleep(1)
        # the timer was stopped or the window was closed
        print("long running task is exiting")

    def InitUI(self):
        pnl = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        hbox3 = wx.BoxSizer(wx.HORIZONTAL)

        self.btn2 = wx.Button(pnl, wx.ID_STOP)
        self.text = wx.StaticText(pnl)
        self.count = wx.StaticText(pnl)

        self.Bind(wx.EVT_BUTTON, self.OnStop, self.btn2)
        self.gauge = wx.Gauge(pnl, 20, size=(250, -1), style=wx.GA_HORIZONTAL)
        hbox1.Add(self.gauge, proportion=1, flag=wx.ALIGN_CENTRE)

        hbox2.Add(self.btn2, proportion=1)
        hbox3.Add(self.text, proportion=1, flag=wx.RIGHT, border=50)
        hbox3.Add(self.count, proportion=1)

        vbox.Add((0, 30))

        vbox.Add(hbox1, flag=wx.ALIGN_CENTRE)

        vbox.Add((0, 20))

        vbox.Add(hbox2, proportion=1, flag=wx.ALIGN_CENTRE)
        vbox.Add(hbox3, proportion=1, flag=wx.ALIGN_CENTRE)

        pnl.SetSizer(vbox)

        self.SetTitle('Gauge')
        self.Centre()

    def OnStop(self, e):
        self.timer.Stop()
        self.text.SetLabel('Task Interrupted')

    def OnTimer(self, e):
        self.gauge.Pulse()
        self.SetTimeLabel()

    def get_elapsed_time(self):
        val = round(time.time() - self.start_time, 1)
        hours = val / 3600
        minutes = (val % 3600) / 60
        seconds = val % 60
        strs = ("%lu:%02lu:%02lu") % (hours, minutes, seconds)

        return strs

    def SetTimeLabel(self):
        self.text.SetLabel("{elapsed} seconds elapsed".format(elapsed=self.get_elapsed_time()))


def main():
    app = wx.App()
    ex = Example(None)
    ex.Show()
    app.MainLoop()


if __name__ == '__main__':
    main()
1 голос
/ 27 сентября 2019

Это пример, основанный на коде, который я рекомендовал в своем комментарии.
Кнопка Пуск / Стоп запускает или останавливает загрузку файла.
Кнопка Other task просто печатает содержимое полей textctrl какдоказательство того, что программа не заблокирована потоком загрузки файла.

import wx
import time
from threading import Thread
import wx.lib.newevent
progress_event, EVT_PROGRESS_EVENT = wx.lib.newevent.NewEvent()
load_status=["File Loading","File Loaded","Cancelled"]

class Model(Thread):
    def __init__(self,parent):
        Thread.__init__(self)
        self.stopthread = 0
        self.target = parent
        #self.start()

    def run(self):
        line_counter = 0
        with open('../xxx.html', 'r') as f:
            while not self.stopthread:
                    line = f.readline()
                    if not line:
                        break
                    line_counter += 1
                    print(line_counter)
                    if self.stopthread:
                        break
                    time.sleep(0.05)
                    evt = progress_event(count=line_counter, status=self.stopthread)
                    wx.PostEvent(self.target, evt)
            if self.stopthread == 0:
                self.stopthread = 1
        evt = progress_event(count=line_counter, status=self.stopthread)
        wx.PostEvent(self.target, evt)

    def terminate(self):
        self.stopthread = 2

class View(wx.Frame):
    def __init__(self, parent, title):
        super(View, self).__init__(parent, title=title, size=(400, 400))
        self.InitUI()

    def InitUI(self):
        self.vbox = wx.BoxSizer(wx.VERTICAL)
        self.fgs = wx.FlexGridSizer(6, 2, 10, 25)
        id = wx.StaticText(self, label="ID:")
        firstName = wx.StaticText(self, label="First name:")
        lastName = wx.StaticText(self, label="Last name:")
        self.id = wx.TextCtrl(self)
        self.firstName = wx.TextCtrl(self)
        self.lastName = wx.TextCtrl(self)
        self.stop = wx.Button(self, -1, "Start")
        self.other = wx.Button(self, -1, "Other task")

        self.fgs.AddMany([id, (self.id, 1, wx.EXPAND),
                         firstName, (self.firstName, 1, wx.EXPAND),
                         lastName, (self.lastName, 1, wx.EXPAND),
                         (self.stop,1,wx.EXPAND),
                         (self.other,1,wx.EXPAND)])

        self.vbox.Add(self.fgs, proportion=1, flag=wx.ALL | wx.EXPAND,border=15)
        #Bind to the progress event issued by the thread
        self.Bind(EVT_PROGRESS_EVENT, self.OnProgress)
        #Bind to Stop button
        self.stop.Bind(wx.EVT_BUTTON, self.OnStartStop)
        #Bind to Other task button
        self.other.Bind(wx.EVT_BUTTON, self.OnOther)
        #Bind to Exit on frame close
        self.Bind(wx.EVT_CLOSE, self.OnExit)
        self.SetSizer(self.vbox)
        self.Layout()

        self.statusbar = self.CreateStatusBar(2)
        self.text = wx.StaticText(self.statusbar,-1,("No File loaded"))
        self.progress = wx.Gauge(self.statusbar, range=20)
        sizer = wx.BoxSizer(wx.HORIZONTAL)
        sizer.Add(self.text, 0, wx.ALIGN_TOP|wx.ALL, 5)
        sizer.Add(self.progress, 1, wx.ALIGN_TOP|wx.ALL, 5)
        self.statusbar.SetSizer(sizer)
        #wx.BeginBusyCursor()
        self.loadthread = Model(self)


    def OnProgress(self, event):
        self.text.SetLabel(load_status[event.status])
        #self.progress.SetValue(event.count)
        #or for indeterminate progress
        self.progress.Pulse()
        if event.status != 0:
            wx.EndBusyCursor()
            self.Update()
            time.sleep(1)
            #self.statusbar.Hide()
            #Re-set thread in case it needs to be restarted
            self.loadthread = Model(self)
            self.stop.SetLabel("Start")
            self.progress.SetValue(0)
            self.text.SetLabel("")

    def OnStartStop(self, event):
        if self.loadthread.isAlive():
            self.loadthread.terminate() # Shutdown the thread
            self.loadthread.join() # Wait for it to finish
            #Re-set thread in case it needs to be restarted
            self.loadthread = Model(self)
            self.stop.SetLabel("Start")
            self.progress.SetValue(0)
            self.text.SetLabel("")
        else:
            wx.BeginBusyCursor()
            self.loadthread.start()
            self.stop.SetLabel("Stop")

    def OnExit(self, event):
        if self.loadthread.isAlive():
            self.loadthread.terminate() # Shutdown the thread
            self.loadthread.join() # Wait for it to finish
        self.Destroy()

    def OnOther(self, event):
        print("Other Task")
        print(self.id.GetValue())
        print(self.firstName.GetValue())
        print(self.lastName.GetValue())

class Controller:
    def __init__(self):
        self.view = View(None, title='Test')
        self.view.Show()

def main():
    app = wx.App()
    controller = Controller()
    app.MainLoop()

if __name__ == '__main__':
    main()

enter image description here

0 голосов
/ 26 сентября 2019

Этот датчик работает с потоком, который читает файл.Когда вам нужно прочитать Txt-файл, датчик работает быстро, но когда вам нужно прочитать Docx, датчик замедляется хуже, когда вам приходится читать тексты изображения, датчик вылетает из GUI.Я хочу избежать моих сбоев графического интерфейса.Если возможно, стабилизируйте скорость датчика.

import time
import datetime
class Example(wx.Frame):

    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)

        self.Bind(wx.EVT_TIMER, self.OnTimer)
        self.gspeed = 20
        self.timer = wx.Timer(self)
        self.timer.Start(self.gspeed)

        self.star = True
        self.start_time = time.time()

        self.InitUI()

    def InitUI(self):

        pnl = wx.Panel(self)
        vbox = wx.BoxSizer(wx.VERTICAL)
        hbox1 = wx.BoxSizer(wx.HORIZONTAL)
        hbox2 = wx.BoxSizer(wx.HORIZONTAL)
        hbox3 = wx.BoxSizer(wx.HORIZONTAL)


        self.btn2 = wx.Button(pnl, wx.ID_STOP)
        self.text = wx.StaticText(pnl)
        self.count = wx.StaticText(pnl)

        self.Bind(wx.EVT_BUTTON, self.OnStop, self.btn2)
        self.gauge = wx.Gauge(pnl,20, size=(250, -1), style = wx.GA_HORIZONTAL)
        hbox1.Add(self.gauge, proportion=1, flag=wx.ALIGN_CENTRE)

        hbox2.Add(self.btn2, proportion=1)
        hbox3.Add(self.text, proportion=1, flag=wx.RIGHT, border=50)
        hbox3.Add(self.count, proportion=1)

        vbox.Add((0, 30))

        vbox.Add(hbox1, flag=wx.ALIGN_CENTRE)

        vbox.Add((0, 20))

        vbox.Add(hbox2, proportion=1, flag=wx.ALIGN_CENTRE)
        vbox.Add(hbox3, proportion=1, flag=wx.ALIGN_CENTRE)

        pnl.SetSizer(vbox)

        self.SetTitle('Gauge')
        self.Centre()


    def OnStop(self, e):

        self.timer.Stop()
        self.text.SetLabel('Task Interrupted')

    def OnTimer(self, e):

        self.gauge.Pulse()
        self.SetTimeLabel()

    def get_elapsed_time(self):
        val = round(time.time() - self.start_time, 1)
        hours = val/3600
        minutes = (val%3600)/60
        seconds = val%60
        strs = ("%lu:%02lu:%02lu")%(hours, minutes, seconds)

        return strs

    def SetTimeLabel(self):

        self.text.SetLabel("{elapsed} seconds elapsed".format(elapsed=self.get_elapsed_time()))


def main():

    app = wx.App()
    ex = Example(None)
    ex.Show()
    app.MainLoop()


if __name__ == '__main__':
    main()

...