как запустить систему чтения карт nfcpy в приложении с графическим интерфейсом wxPython

Я новичок в приложении wxPython с графическим интерфейсом.

я хочу создать свой скрипт Python как приложение с графическим интерфейсом

Это мой пример сценария

import binascii
import nfc

class MyCardReader(object):

   def on_connect(self, tag):
      print "touched"
      self.idm = binascii.hexlify(tag.idm)
      return True

   def read_id(self):
      clf = nfc.ContactlessFrontend('usb')
      try:
         clf.connect(rdwr={'on-connect': self.on_connect})
      finally:
         clf.close()

if __name__ == '__main__':
  cr = MyCardReader()
  while True:
    print "touch card:"
    cr.read_id()
    print "released"
    print cr.idm

как запустить приведенный выше скрипт как приложение с графическим интерфейсом, используя wxPython, я уже пробовал, но он не работает, что не так в моем коде.

#-*- encoding: utf-8 -*-
import wx
import nfc
import binascii
class MyFrame(wx.Frame):

   def __init__(self, parent, title):
      wx.Frame.__init__(self, parent, title=title, size=(400, 500))
      panel = wx.Panel(self)
      self.Show(True)
      while True:
        clf = nfc.ContactlessFrontend('usb')
        clf.connect(rdwr={'on-connect': self.on_connect})
        self.text = wx.StaticText(panel, label='i want to print the return value here', pos=(100, 100))

  def on_connect(self, tag):
      self.idm = binascii.hexlify(tag.idm)
      return self.idm

app = wx.App(False)
frame = MyFrame(None, 'card reader app')
app.MainLoop()

person thirdwave    schedule 25.09.2017    source источник


Ответы (2)


Метод nfc.ContactlessFrontend.connect() работает в контексте потока вызывающей стороны, поэтому он не возвращает значение до тех пор, пока не будет подключен хотя бы один тег (и если обратный вызов «при подключении» возвращает значение True, он будет ждать, пока тег не исчезнет). wx.App.mainLoop() также запускается в контексте потока вызывающей стороны для отправки оконных событий. Таким образом, правильный способ — запускать обнаружение тегов в отдельном потоке и отправлять события в кадр рендеринга. Ниже приведен пример, который показывает идентификатор метки всякий раз, когда метка находится близко к считывателю.

#!/usr/bin/env python
import wx
import wx.lib.newevent
import nfc
import threading
from binascii import hexlify

ShowCardEvent, SHOW_CARD_EVENT = wx.lib.newevent.NewEvent()
GoneCardEvent, GONE_CARD_EVENT = wx.lib.newevent.NewEvent()


class TagReader(threading.Thread):
    def __init__(self, wx_frame):
        super(TagReader, self).__init__(name="TagReader")
        self.terminate = False
        self.wx_frame = wx_frame

    def run(self):
        clf = nfc.ContactlessFrontend('usb')
        rdwr_options = {
            'on-connect': self.on_tag_connect,
            'on-release': self.on_tag_release
        }
        while not self.terminate:
            clf.connect(rdwr=rdwr_options, terminate=lambda: self.terminate)

    def on_tag_connect(self, tag):
        wx.PostEvent(self.wx_frame, ShowCardEvent(tag=tag))
        return True

    def on_tag_release(self, tag):
        wx.PostEvent(self.wx_frame, GoneCardEvent())


class Frame(wx.Frame):
    def __init__(self, title):
        super(Frame, self).__init__(None, title=title, size=(500, 200))
        self.text = wx.StaticText(wx.Panel(self), pos=(100, 100))
        self.Bind(SHOW_CARD_EVENT, self.show_card_event)
        self.Bind(GONE_CARD_EVENT, self.gone_card_event)
        self.Bind(wx.EVT_CLOSE, self.close_window_event)
        wx.PostEvent(self, GoneCardEvent())
        self.Show()

    def close_window_event(self, event):
        self.Destroy()

    def show_card_event(self, event):
        self.text.SetLabel("Card ID {}".format(hexlify(event.tag.identifier)))

    def gone_card_event(self, event):
        self.text.SetLabel("no card")


app = wx.App()
reader = TagReader(Frame('card reader app'))
reader.start()
app.MainLoop()
reader.terminate = True  # tell the reader to terminate
reader.join()  # and wait for the reader thread to finish
person Stephen Tiedemann    schedule 25.09.2017
comment
Большое спасибо за объяснение, Стивен. Это то, что я хочу сделать. - person thirdwave; 26.09.2017
comment
@HAUMUNTUANG Если это ответ на ваш вопрос, не забудьте Accept его, нажав на серый значок Tick слева. - person Rolf of Saxony; 27.09.2017

Вы загнали свой код в бесконечный цикл While True, а это означает, что основной цикл Gui никогда не запустится.
Вам следует либо добавить event на основе ввода, поступающего от устройства чтения карт, либо для начала просто добавьте кнопку и получить доступ к считывателю при нажатии кнопки. Это поможет вам быстро приступить к работе.
Вот ваш код, настроенный для работы на моем компьютере, просто чтобы доказать, что он работает.
Обратите внимание на использование self.text.SetLabel()

import wx
#import nfc
import binascii
class MyFrame(wx.Frame):

    def __init__(self, parent, title):
        wx.Frame.__init__(self, parent, title=title, size=(400, 500))
        panel = wx.Panel(self)
        self.text = wx.StaticText(panel, label='i want to print the return value here', pos=(100, 100))
        self.read = wx.Button(panel, -1, label="Read Card", pos=(100, 200))
        self.read.Bind(wx.EVT_BUTTON, self.on_button)
        self.Show()
        self.n = 0

    def on_button(self,event):
#        clf = nfc.ContactlessFrontend('usb')
#        clf.connect(rdwr={'on-connect': self.on_connect})
        self.n+=1
        self.on_connect("abc")
        self.text.SetLabel("Card Value "+self.idm+" "+str(self.n))

    def on_connect(self, tag):
        self.idm = binascii.hexlify(tag)#.idm)
        return self.idm

app = wx.App()
frame = MyFrame(None, 'card reader app')
app.MainLoop()

введите здесь описание изображения

person Rolf of Saxony    schedule 25.09.2017
comment
Спасибо @Rolf из Саксонии - person thirdwave; 25.09.2017