2012-05-08 63 views
2

我试图建立一个PyQt应用程序(其中包括)有能力通过QTextEdit框功能像串行终端程序(超级终端,TeraTerm等),我读过来自PySerial页面的一些例子,我想我已经设法使接收数据线程正常工作,但可能不尽可能有效。终端线程使用PyQt

我的问题是如何取出QTextEdit框中的最后一个输入字符并将其发送出串行连接?我尝试过使用QTextEdit发出的textChanged信号,但是它会发送我输入的和它接收到的所有信息。我已经尝试在我的主要GUI类中设置eventFilter,但我无法弄清楚如何将它转换为另一个文件中的串行函数。我想要一个单独的线程来侦听eventFilter发出的信号吗?我怎么做?有没有更优雅的方式来做到这一点?

我敢肯定,我已经设法推翻了这一点,解决方案很简单,但我有点挣扎。我会附上相关的代码片段(不是完整的代码集),也许有人可以指出我正确的方向。如果有人也认为我正在做的穿线可以以更有效的方式完成,那么请把这个穿线给我!

感谢任何人都可以提供的帮助!

主文件:

import sys 
from PyQt4 import QtGui 
from MainGUI import TestGUI 
from SerialClasses import * 
from SerialMiniterm import * 

class StartMainWindow(QtGui.QMainWindow):  
    def __init__(self, parent=None): 
     super(StartMainWindow, self).__init__(parent) 
     self.ui = TestGUI() 
     self.ui.setupUi(self)  
     self.ui.serialTextEditBox.installEventFilter(self) 

    def eventFilter(self, source, event): 
     if (event.type() == QtCore.QEvent.KeyPress and source is self.ui.serialTextEditBox): 
      # print some debug statements to console 
      if (event.key() == QtCore.Qt.Key_Tab): 
       print ('Tab pressed') 
      print ('key pressed: %s' % event.text()) 
      print ('code pressed: %d' % event.key()) 
      # do i emit a signal here? how do i catch it in thread? 
      self.emit(QtCore.SIGNAL('transmitSerialData(QString)'), event.key()) 
      return True 
     return QtGui.QTextEdit.eventFilter(self, source, event) 

    def serialConnectCallback(self): 
     self.miniterm = SerialMiniterm(self.ui, self.SerialSettings) 
     self.miniterm.start() 
     temp = self.SerialSettings.Port + 1 
     self.ui.serialLabel.setText("<font color = green>Serial Terminal Connected on COM%d" % temp) 

if __name__ == "__main__": 
    app = QtGui.QApplication(sys.argv) 
    app.setStyle("Cleanlooks") 
    myapp = StartMainWindow() 
    myapp.show() 
    sys.exit(app.exec_()) 

SerialMiniterm.py:

import serial 
from PyQt4 import QtGui, QtCore 

def character(b): 
    return b 

class SerialMiniterm(object): 
    def __init__(self, ui, SerialSettings): 
     self.SerialSettings = SerialSettings 
     self.ui = ui 
     self.serial = serial.Serial(self.SerialSettings.Port, self.SerialSettings.BaudRate, parity=self.SerialSettings.Parity, rtscts=self.SerialSettings.RTS_CTS, xonxoff=self.SerialSettings.Xon_Xoff, timeout=1) 
     self.repr_mode = self.SerialSettings.RxMode 
     self.convert_outgoing = self.SerialSettings.NewlineMode 
     self.newline = NEWLINE_CONVERISON_MAP[self.convert_outgoing] 
     self.dtr_state = True 
     self.rts_state = True 
     self.break_state = False 

    def _start_reader(self): 
     """Start reader thread""" 
     self._reader_alive = True 
     self.receiver_thread = ReaderThread(self.alive, self._reader_alive, self.repr_mode, self.convert_outgoing, self.serial) 
     self.receiver_thread.connect(self.receiver_thread, QtCore.SIGNAL("updateSerialTextBox(QString)"), self.updateTextBox) 
     self.receiver_thread.start() 

    def _stop_reader(self): 
     """Stop reader thread only, wait for clean exit of thread""" 
     self._reader_alive = False 
     self.receiver_thread.join() 

    def updateTextBox(self, q): 
     self.ui.serialTextEditBox.insertPlainText(q) 
     self.ui.serialTextEditBox.moveCursor(QtGui.QTextCursor.End) 
     #print "got here with value %s..." % q 

    def start(self): 
     self.alive = True 
     self._start_reader() 
     # how do i handle transmitter thread? 

    def stop(self): 
     self.alive = False 

    def join(self, transmit_only=False): 
     self.transmitter_thread.join() 
     if not transmit_only: 
      self.receiver_thread.join() 

class ReaderThread(QtCore.QThread):  
    def __init__(self, alive, _reader_alive, repr_mode, convert_outgoing, serial, parent=None): 
     QtCore.QThread.__init__(self, parent) 
     self.alive = alive 
     self._reader_alive = _reader_alive 
     self.repr_mode = repr_mode 
     self.convert_outgoing = convert_outgoing 
     self.serial = serial 

    def __del__(self): 
     self.wait() 

    def run(self): 
     """loop and copy serial->console""" 
     while self.alive and self._reader_alive: 
      data = self.serial.read(self.serial.inWaiting()) 
      if data:       #check if not timeout 
       q = data 
       self.emit(QtCore.SIGNAL('updateSerialTextBox(QString)'), q) 

回答

1

像这样的事情?

from PyQt4 import QtCore, QtGui 
app = QtGui.QApplication([]) 

class Terminal(QtGui.QPlainTextEdit): 
    def keyPressEvent(self, event): 
     print event.text() 
     return QtGui.QPlainTextEdit.keyPressEvent(self, event) 

term = Terminal() 
term.show()