Как запустить код, только когда я нажимаю на конструктор button..python/wxpython/boa

Я разрабатываю графический интерфейс с помощью wxPython (Boa Constructor IDE). Мой графический интерфейс имеет следующее:

  1. Богатый текстовый контроль
  2. Кнопка Пуск
  3. Кнопка Стоп

Мое требование состоит в том, чтобы при нажатии кнопки START цифры (1, 2, 3 и т. Д.) Начинали печатать в текстовом элементе управления; он должен остановиться, когда я нажимаю кнопку СТОП. Код и графический интерфейс, как показано. Какие изменения мне нужно внести, чтобы соответствовать моим требованиям?

Внешность:

Код:

import wx
import wx.richtext

def create(parent):
    return Frame3(parent)

[wxID_FRAME3, wxID_FRAME3BUTTON1, wxID_FRAME3BUTTON2, wxID_FRAME3PANEL1, 
 wxID_FRAME3RICHTEXTCTRL1, 
] = [wx.NewId() for _init_ctrls in range(5)]

class Frame3(wx.Frame):
    def _init_ctrls(self, prnt):
        # generated method, don't edit
        wx.Frame.__init__(self, id=wxID_FRAME3, name='', parent=prnt,
              pos=wx.Point(579, 234), size=wx.Size(414, 492),
              style=wx.DEFAULT_FRAME_STYLE, title='Frame3')
        self.SetClientSize(wx.Size(406, 458))

        self.panel1 = wx.Panel(id=wxID_FRAME3PANEL1, name='panel1', parent=self,
              pos=wx.Point(0, 0), size=wx.Size(406, 458),
              style=wx.TAB_TRAVERSAL)

        self.richTextCtrl1 = wx.richtext.RichTextCtrl(id=wxID_FRAME3RICHTEXTCTRL1,
              parent=self.panel1, pos=wx.Point(96, 96), size=wx.Size(200, 100),
              style=wx.richtext.RE_MULTILINE, value=u'')
        self.richTextCtrl1.SetLabel(u'richText')

        self.button2 = wx.Button(id=wxID_FRAME3BUTTON2, label=u'STOP',
              name='button2', parent=self.panel1, pos=wx.Point(256, 280),
              size=wx.Size(75, 23), style=0)
        self.button2.Bind(wx.EVT_BUTTON, self.OnButton2Button,
              id=wxID_FRAME3BUTTON2)

        self.button1 = wx.Button(id=wxID_FRAME3BUTTON1, label=u'START',
              name='button1', parent=self.panel1, pos=wx.Point(88, 280),
              size=wx.Size(75, 23), style=0)
        self.button1.Bind(wx.EVT_BUTTON, self.OnButton1Button,
              id=wxID_FRAME3BUTTON1)

    def __init__(self, parent):
        self._init_ctrls(parent)

    def OnButton1Button(self, event):  #START BUTTON
        event.Skip()

    def OnButton2Button(self, event):  #STOP BUTTON
        event.Skip()


if __name__ == '__main__':
    app = wx.PySimpleApp()
    frame = create(None)
    frame.Show()

    app.MainLoop()

2 ответа

Решение

Резюме

В общем, это приемлемый способ сделать это в wxPython, и он идет прямо из документации.

  1. Создайте новое событие "data".

  2. Заставьте ваш контроллер прослушивать события "data"

  3. Давайте нажмем кнопку "Пуск", чтобы запустить поток, который увеличивает счетчик и отправляет событие "данные" в ваше окно со значением счетчика.

  4. После получения события, добавьте значение к вашему RichTextCtrl

пример

Вот пример. Обратите внимание, в частности, на использование Connect() прослушивать входящие события значения.

import wx
import wx.richtext
import threading
import time


EVT_ID_VALUE = wx.NewId()

class DataEvent(wx.PyEvent):
  def __init__(self, data):
    wx.PyEvent.__init__(self)
    self.SetEventType(EVT_ID_VALUE)
    self.data=data


class Frame3(wx.Frame):
  def __init__(self, parent, title):
    self.counter = 0
    self.worker = None

    wx.Frame.__init__(
      self, name='', 
      parent=parent,
      pos=wx.Point(579, 234), 
      size=wx.Size(414, 492),
      style=wx.DEFAULT_FRAME_STYLE, title='Frame3'
    )
    self.panel1 = wx.Panel(
      name='panel1', 
      parent=self,
      pos=wx.Point(0, 0), 
      size=wx.Size(406, 458),
      style=wx.TAB_TRAVERSAL
    )
    self.richTextCtrl1 = wx.richtext.RichTextCtrl(
      parent=self.panel1, 
      pos=wx.Point(96, 96), 
      size=wx.Size(200, 100),
      style=wx.richtext.RE_MULTILINE, 
      value=u''
    )
    self.richTextCtrl1.SetLabel(u'richText')
    self.richTextCtrl1.SetScrollbars(20,20,50,50)
    self.button2 = wx.Button(
      label=u'STOP',
      name='button2', 
      parent=self.panel1, 
      pos=wx.Point(256, 280),
      size=wx.Size(75, 23), 
      style=0
    )
    self.button2.Bind(
      wx.EVT_BUTTON, 
      self.OnStop
    )
    self.button1 = wx.Button(
      label=u'START',
      name='button1', 
      parent=self.panel1, 
      pos=wx.Point(88, 280),
      size=wx.Size(75, 23), 
      style=0
    )
    self.button1.Bind(
      wx.EVT_BUTTON, 
      self.OnStart
    )
    self.Connect(-1, -1, EVT_ID_VALUE, self.OnValue )

  def OnValue(self, event):
    self.richTextCtrl1.AppendText("%d\n"%event.data)


  def OnStart(self, event):  #START BUTTON
    self.richTextCtrl1.AppendText("START\n")
    if not self.worker:
      self.worker = WorkerThread(self)
      self.worker.start() 

  def OnStop(self, event):  #STOP BUTTON
    self.richTextCtrl1.AppendText("STOP\n")
    if self.worker:
      self.worker.stop() 


class WorkerThread(threading.Thread):
  def __init__(self, notify_window):
    threading.Thread.__init__(self)
    self.counter = 0
    self._notify_window = notify_window
    self.abort = False 

  def run(self):
    while not self.abort:
      self.counter += 1
      wx.PostEvent(self._notify_window, DataEvent(self.counter))
      time.sleep(1)

  def stop(self):
      self.abort = True



if __name__ == '__main__':
    app = wx.App()
    frame = Frame3(None, "My Hello App")
    frame.Show(True)
    app.MainLoop()

Для чего-то столь же простого, как это, я бы просто использовал wx.Timer вместо того, чтобы возиться с потоками. как в этом уроке.

Если вы действительно хотите использовать потоки, вам, вероятно, захочется прочитать одно из следующего:

Другие вопросы по тегам