[pyqt5-pyserial實(shí)現(xiàn)一個(gè)串口調(diào)試工具記錄](méi)

遇到的問(wèn)題

1. 程序結(jié)構(gòu)

  • 創(chuàng)建一個(gè)主窗口的類(lèi):在里面主要實(shí)現(xiàn)窗口UI的繪制,并定義一些槽函數(shù)接口
  • 創(chuàng)建主框架類(lèi):該類(lèi)繼承自主窗口類(lèi),并實(shí)現(xiàn)主窗口類(lèi)中的槽函數(shù),在該類(lèi)中創(chuàng)建串口接收線(xiàn)程
  • 串口接收線(xiàn)程類(lèi):該類(lèi)繼承自QtCore.QThread類(lèi)脆贵,主要進(jìn)行串口接收處理

2. 多線(xiàn)程
在程序結(jié)構(gòu)上,需要建立兩個(gè)線(xiàn)程:主線(xiàn)程串口接收線(xiàn)程嘉汰;主線(xiàn)程在程序啟動(dòng)時(shí)就存在丹禀;串口接收線(xiàn)程主要負(fù)責(zé)在后臺(tái)不斷的讀取串口接收緩存中的數(shù)據(jù),判斷是否有數(shù)據(jù)到來(lái)。多線(xiàn)程通過(guò)創(chuàng)立一個(gè)繼承QtCore.QThread的類(lèi)來(lái)實(shí)現(xiàn)双泪;為什么沒(méi)有使用threading.Thread持搜?因?yàn)闆](méi)有threading.Thread類(lèi)中找到終止線(xiàn)程的API,所以改用QtCore.QThread焙矛。
終止線(xiàn)程:
self.serialThread.quit() # serialThread為我創(chuàng)建的線(xiàn)程實(shí)例對(duì)象

  1. 點(diǎn)擊窗口的"X"關(guān)閉窗口時(shí)葫盼,需要對(duì)線(xiàn)程資源進(jìn)行清理
    當(dāng)點(diǎn)擊窗口的"X"時(shí),我們可以通過(guò)在我們的窗口類(lèi)中重寫(xiě)closeEvent()方法實(shí)現(xiàn)最后的資源清理村斟,在該串口程序中贫导,實(shí)現(xiàn)的功能如下:
# 重寫(xiě)關(guān)閉窗口事件
    def closeEvent(self, event):
        if self.serialPara['serialPt'].isOpen() == True:  # 如果串口打開(kāi)了,說(shuō)明線(xiàn)程正在運(yùn)行蟆盹,需要終止線(xiàn)程
            self.serialThread.quit()  # 終止線(xiàn)程
  1. 對(duì)接收的bytes數(shù)據(jù)進(jìn)行顯示處理
    通過(guò)串口接收到的數(shù)據(jù)是bytes類(lèi)型孩灯,類(lèi)似于:b'\x12\xde\x7f' 這種形式

對(duì)于0~ 0x7f之間的數(shù)據(jù)可以使用decode()進(jìn)行解碼,但是0x7f之后的數(shù)據(jù)使用decode()解碼時(shí)逾滥,會(huì)提示不能對(duì)utf-8的字符使用decode()進(jìn)行解碼峰档,因?yàn)閍scii碼的范圍在0 ~ 0x7f之間

解決方法:在程序中,需要對(duì)發(fā)送的數(shù)據(jù)進(jìn)行格式選擇:hex發(fā)送或ascii碼發(fā)送兩種形式寨昙,

  1. 當(dāng)使用ascii碼形式發(fā)送數(shù)據(jù)時(shí)直接使用decode()對(duì)接收到的數(shù)據(jù)進(jìn)行解碼
  2. 當(dāng)使用hex碼形式發(fā)送數(shù)據(jù)時(shí)讥巡,我們的串口工具需要將數(shù)據(jù)一個(gè)一個(gè)的取出來(lái),然后使用hex()轉(zhuǎn)換為hex形式的數(shù)據(jù)舔哪,然后去除0x欢顷,再將它們以空格為分割符拼接在一起;代碼如下:
def run(self):
        print ("啟動(dòng)線(xiàn)程")
        while True:
            # 獲得接收到的字符
            count = self.Ser.inWaiting()
            if count != 0:
                dealStr = ""
                # 讀串口數(shù)據(jù)
                recv = self.Ser.read(count)
                recv = recv.upper()
                # 在這里將接收到數(shù)據(jù)進(jìn)行區(qū)分:hex 或 字符串
                # hex 格式:\xYY\xYY\xYY捉蚤,如果接收到的字符是這種格式抬驴,則說(shuō)明是hex字符,我們需要將
                # \x去除掉外里,取出YY怎爵,然后組成字符串返回
                # 如果接收到的是字符串特石,則使用decode進(jìn)行解碼
                print ("接收到的數(shù)據(jù) %s \n類(lèi)型為: %s\n" % (recv,  type(recv)))
                # 嘗試使用decode解碼盅蝗,如果失敗,則表示接收到的數(shù)據(jù)為hex發(fā)送過(guò)來(lái)的數(shù)據(jù)
                try:
                    dealStr = recv.decode()
                except (TypeError,  UnicodeDecodeError):
                    for i in range(len(recv)):
                        print (hex(recv[i])[2:])
                        dealStr += hex(recv[i])[2:]
                        dealStr +=' '
                    dealStr.rstrip(' ')
                print ("處理后的數(shù)據(jù) %s \n類(lèi)型為: %s\n" % (dealStr,  type(dealStr)))
                
                # 顯示接收到的數(shù)據(jù)
                self.dispContent(dealStr)
                # 清空接收緩沖區(qū)
                self.Ser.flushInput()
            time.sleep(0.1)
            if self.Ser.isOpen() == False:
                print ("關(guān)閉線(xiàn)程")
                self.quit()
                return

程序代碼如下:

# -*- coding: utf-8 -*-

from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5 import QtWidgets 
import sys
import serial
import win32api
import win32com
import binascii
import struct
import time
import threading
import codecs  

class MainDialog(QtWidgets.QDialog):
    # ---定義屬性
    # 發(fā)送buf
    def __init__(self, parent = None):
        super(MainDialog, self).__init__()
        self.setWindowTitle(self.tr("串口助手"))

        self.serialNo = ("COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9")
        self.serialBaud = (1200, 2400, 4800, 9600, 14400, 19200, 38400, 56000, 57600, 115200)
        self.serialChk = {"None": serial.PARITY_NONE,
                          "Odd": serial.PARITY_EVEN,
                          "Even": serial.PARITY_ODD}
        self.serialChkCode = ("None", "Odd", "Even")
        self.serialStopBitCode = (serial.STOPBITS_ONE, serial.STOPBITS_ONE_POINT_FIVE, serial.STOPBITS_TWO)
        self.serialPara  = {
                          "comNo": 0,
                          "baud": 9600,
                          "stopBit": 1,
                          "dataBit": 8,
                          "chk": "odd",
                          "serialPt": "串口1"}
        # 串口狀態(tài)姆蘸,打開(kāi)/關(guān)閉
        self.isSerialOpen = False
        self.sendBuf = []
        self.initUI()


    def initUI(self):
        layout = QtWidgets.QVBoxLayout(self)
        # 內(nèi)容顯示區(qū)
        self.contentDispText = QtWidgets.QTextEdit()
        self.contentDispText.setReadOnly(True)
        # 設(shè)置區(qū)
        line1_inputLabel = QtWidgets.QLabel(self.tr("輸入框:"))
        self.line1_inputLineEdit = QtWidgets.QLineEdit()
        self.line1_sendButton = QtWidgets.QPushButton(self.tr("發(fā)送"))
        self.line1_clearButton = QtWidgets.QPushButton(self.tr("清除"))
        self.line1_hexdispCheckBox = QtWidgets.QCheckBox(self.tr("HEX顯示"))

        # 第二行
        line2_serialNoLabel = QtWidgets.QLabel(self.tr("串口號(hào):"))
        self.line2_serialComboBox = QtWidgets.QComboBox()
        for uart in self.serialNo:
            self.line2_serialComboBox.insertItem(self.serialNo.index(uart), self.tr(uart))

        line2_serialBaudLabel = QtWidgets.QLabel(self.tr("波特率:"))
        self.line2_serialBaudComboBox = QtWidgets.QComboBox()
        for baud in self.serialBaud:
            self.line2_serialBaudComboBox.insertItem(self.serialBaud.index(baud), self.tr(str(baud)))
        self.line2_serialBaudComboBox.setCurrentIndex(3)

        self.line2_OpenSerialButton = QtWidgets.QPushButton(self.tr("打開(kāi)串口"))

        # 此處還要添加一個(gè)指示燈墩莫,考慮是否可以使用圖片表示工作狀態(tài)

        self.line2_hexSendCheckBox = QtWidgets.QCheckBox(self.tr("HEX發(fā)送"))
        self.line2_hexSendCheckBox.setChecked(True)

        # 第三行
        line3_dataBitLabel = QtWidgets.QLabel(self.tr("數(shù)據(jù)位:"))
        self.line3_dataBitComboBox = QtWidgets.QComboBox()
        i = 0
        for bit in range(5, 9):
            self.line3_dataBitComboBox.insertItem(i, self.tr(str(bit)))
            i += 1
        self.line3_dataBitComboBox.setCurrentIndex(3)
        line3_checkLabel = QtWidgets.QLabel(self.tr("校驗(yàn)位:"))
        self.line3_checkComboBox = QtWidgets.QComboBox()
        for chk in self.serialChkCode:
            self.line3_checkComboBox.insertItem(self.serialChkCode.index(chk), self.tr(chk))
        line3_stopBitLabel = QtWidgets.QLabel(self.tr("停止位:"))
        self.line3_stopBitComboBox = QtWidgets.QComboBox()
        self.line3_stopBitComboBox.insertItem(0, self.tr('1'))
        self.line3_stopBitComboBox.insertItem(1, self.tr('1.5'))
        self.line3_stopBitComboBox.insertItem(2, self.tr('2'))
        self.line3_stopBitComboBox.setCurrentIndex(0)

        # 此處還需要添加一個(gè)擴(kuò)展功能
        setHbox = QtWidgets.QHBoxLayout()
        setGridLayout =  QtWidgets.QGridLayout()
        setGridLayout.setContentsMargins(0,  0,  0,  0)
        setGridLayout.setSpacing(10)
        setGridLayout.addWidget(line1_inputLabel, 0, 0)
        setGridLayout.addWidget(self.line1_inputLineEdit, 0, 1, 1, 3)
        setGridLayout.addWidget(self.line1_sendButton, 0, 4)
        setGridLayout.addWidget(self.line1_clearButton, 0, 5)
        setGridLayout.addWidget(self.line1_hexdispCheckBox, 0, 6)

        setGridLayout.addWidget(line2_serialNoLabel, 1, 0)
        setGridLayout.addWidget(self.line2_serialComboBox, 1, 1)
        setGridLayout.addWidget(line2_serialBaudLabel, 1, 2)
        setGridLayout.addWidget(self.line2_serialBaudComboBox, 1, 3)
        setGridLayout.addWidget(self.line2_OpenSerialButton, 1, 4)
        setGridLayout.addWidget(self.line2_hexSendCheckBox, 1, 6)

        setGridLayout.addWidget(line3_dataBitLabel, 2, 0)
        setGridLayout.addWidget(self.line3_dataBitComboBox, 2, 1)
        setGridLayout.addWidget(line3_checkLabel, 2, 2)
        setGridLayout.addWidget(self.line3_checkComboBox, 2, 3)
        setGridLayout.addWidget(line3_stopBitLabel, 2, 4)
        setGridLayout.addWidget(self.line3_stopBitComboBox, 2, 5)

        setHbox.addLayout(setGridLayout)
        setHbox.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
        layout.addWidget(self.contentDispText)
        layout.addLayout(setHbox)

        # -----對(duì)控件進(jìn)行初始化----
        self.line1_sendButton.setEnabled(False)     # 在沒(méi)打開(kāi)串口時(shí),設(shè)置串口為無(wú)法操作的狀態(tài)
        # -----為按鈕添加事件-----
        # 串口開(kāi)關(guān)操作
        #self.line2_OpenSerialButton.clicked.connect(self.serialState)
        # 這里省略了receiver逞敷,使用的是connect中的一個(gè)重載函數(shù)狂秦,receiver默認(rèn)為this
        # 在PYQT4.5之后,這是一種新的信號(hào)和槽的 API推捐,老的例子API:  button.clicked.connect(self.onClicked)
        self.line2_OpenSerialButton.clicked.connect(self.serialState)
        #self.connect(self.line2_OpenSerialButton, QtCore.SIGNAL("clicked()"),  self.serialState)
        # 發(fā)送數(shù)據(jù)操作
        self.line1_sendButton.clicked.connect(self.writeStr)
        #self.connect(self.line1_sendButton, QtCore.SIGNAL("clicked()"),   self.writeStr)
        # 清除按鈕
        self.line1_clearButton.clicked.connect(self.contentDispText.clear)
        #self.connect(self.line1_clearButton, QtCore.SIGNAL("clicked()"), self.contentDispText, QtCore.SLOT("clear()"))
        # 窗口的關(guān)閉按鈕

        #self.connect(self, QtCore.SIGNAL(""))
    def setSerialState(self, state):
        pass

    # 顯示收發(fā)數(shù)據(jù)
    def dispContent(self, argvStr):
        pass
        #self.contentDispText.append(r'\n')

    # 處理輸入的數(shù)據(jù)
    def dealInputData(self, argv):
        pass

    def writeStr(self):
        pass

    def serialState(self):
        pass


class ReceiveThread(QtCore.QThread):
    def __init__(self, Ser, dispContent):
        super(ReceiveThread, self).__init__()
        self.Ser = Ser
        self.dispContent = dispContent
        print ("創(chuàng)建線(xiàn)程")

    def run(self):
        print ("啟動(dòng)線(xiàn)程")
        while True:
            # 獲得接收到的字符
            count = self.Ser.inWaiting()
            if count != 0:
                dealStr = ""
                # 讀串口數(shù)據(jù)
                recv = self.Ser.read(count)
                # 在這里將接收到數(shù)據(jù)進(jìn)行區(qū)分:hex 或 字符串
                # hex 格式:\xYY\xYY\xYY裂问,如果接收到的字符是這種格式,則說(shuō)明是hex字符,我們需要將
                # \x去除掉堪簿,取出YY痊乾,然后組成字符串返回
                # 如果接收到的是字符串,則使用decode進(jìn)行解碼
                print ("接收到的數(shù)據(jù) %s \n類(lèi)型為: %s\n" % (recv,  type(recv)))
                try:
                    dealStr = recv.decode()
                except (TypeError,  UnicodeDecodeError):
                    for i in range(len(recv)):
                        print ("不可以嗎")
                        print (hex(recv[i])[2:])
                        dealStr += hex(recv[i])[2:]
                        dealStr +=' '
                    
                print ("處理后的數(shù)據(jù) %s \n類(lèi)型為: %s\n" % (dealStr,  type(dealStr)))
                
                # 顯示接收到的數(shù)據(jù)
                self.dispContent(dealStr)
                # 清空接收緩沖區(qū)
                self.Ser.flushInput()
            time.sleep(0.1)
            if self.Ser.isOpen() == False:
                print ("關(guān)閉線(xiàn)程")
                self.quit()
                return


class SerialFrame(MainDialog):
    def __init__(self, parent = None):
        super(SerialFrame, self).__init__(parent)

    # 重寫(xiě)關(guān)閉窗口事件
    def closeEvent(self, event):
        if self.serialPara['serialPt'].isOpen() == True:
            self.serialThread.quit()

    def getSerialPt(self):
        return self.serialPara['serialPt']

    def setSerialState(self, state):
        self.isSerialOpen = state
        if self.isSerialOpen == True:
            self.line2_OpenSerialButton.setText(self.tr("關(guān)閉串口"))
        else:
            self.line2_OpenSerialButton.setText(self.tr("打開(kāi)串口"))
        # 設(shè)置串口其他參數(shù)的控件為不可設(shè)置狀態(tài)
        self.line2_serialComboBox.setDisabled(state)
        self.line2_serialBaudComboBox.setDisabled(state)
        self.line3_stopBitComboBox.setDisabled(state)
        self.line3_checkComboBox.setDisabled(state)
        self.line3_dataBitComboBox.setDisabled(state)
        self.line1_sendButton.setEnabled(state)  # 在沒(méi)打開(kāi)串口時(shí)椭更,設(shè)置串口為無(wú)法操作的狀態(tài)

    # 顯示收發(fā)數(shù)據(jù)
    def dispContent(self, argvStr):
        isHexDisp = self.line1_hexdispCheckBox.isChecked()
        argvStr = str(argvStr)
        if isHexDisp == False:
            self.contentDispText.append(argvStr)
        else:
            s = ""
            for i in range(len(argvStr)):
                hval = ord(argvStr[i])
                hhex = "%02x" % hval
                s += hhex + ' '
            self.contentDispText.append(s)
            # self.contentDispText.append(r'\n')

    # 處理輸入的數(shù)據(jù)
    def dealInputData(self, argv):
        # 將QString轉(zhuǎn)換為string哪审,因?yàn)橐褂胮ython內(nèi)置的函數(shù),必須進(jìn)行轉(zhuǎn)換
        strList = str(argv)
        if len(strList) == 0:
            QtWidgets.QMessageBox.information(self, "警告", "請(qǐng)輸入字符后虑瀑,再發(fā)送湿滓!", QtWidgets.QMessageBox.Ok)
            return "InPuT eRRoR"
        else:
            # 1. 判斷是HEX發(fā)送還是字符串發(fā)送
            isHex = self.line2_hexSendCheckBox.isChecked()
            if isHex == True:  # HEX發(fā)送
                strList = strList.strip()  # 去除兩邊的空格
                strList = strList.upper()  # 轉(zhuǎn)換為大寫(xiě)字母
                list = []
                list = strList.split()  # 以空格為分隔符分隔字符串,并存入list列表中
                getStr = ""
                # 假如輸入的字符是:ff 55 aa cc 01
                for i in range(len(list)):
                    if len(list[i]) < 2:
                        list[i] = '0' + list[i]
                    getStr += list[i]
                # 到這一步時(shí)字符已經(jīng)被處理為:ff55aacc01
                # 通過(guò)decode("hex")進(jìn)行處理后的數(shù)據(jù)就是兩個(gè)字符為一組的十進(jìn)制數(shù)據(jù)
                # 進(jìn)行異常處理舌狗,當(dāng)進(jìn)行數(shù)據(jù)格式轉(zhuǎn)換時(shí)叽奥,因?yàn)榭赡苡泻芏喾N情況導(dǎo)致轉(zhuǎn)換失敗,所以此處使用異常處理
                try:
                    return codecs.decode(getStr, "hex_codec")
                except ValueError:
                    print ("abdc")
                    QtWidgets.QMessageBox.information(self, "警告", "請(qǐng)輸入十六進(jìn)制字符!", QtWidgets.QMessageBox.Ok)
                    return "InPuT eRRoR"
            else:
                # 字符串發(fā)送痛侍,轉(zhuǎn)換為utf-8格式
                return strList.encode("utf-8")

    def writeStr(self):
        # 讀取數(shù)據(jù)并返回
        inputStr = self.line1_inputLineEdit.text()
        # 處理數(shù)據(jù)
        list = self.dealInputData(inputStr)
        if list == "InPuT eRRoR":
            return
        else:
            # 發(fā)送數(shù)據(jù)
            self.serialPara["serialPt"].write(list)
            # 將發(fā)送的數(shù)據(jù)顯示在文本框中
            self.dispContent(inputStr)

    def serialState(self):
        if self.isSerialOpen == False:
            try:
                # 獲取選擇的串口編號(hào)
                self.serialPara["comNo"] = self.line2_serialComboBox.currentIndex()
                # 獲取串口參數(shù)信息:波特率而线、數(shù)據(jù)位、校驗(yàn)位恋日、停止位
                self.serialPara["baud"] = self.serialBaud[self.line2_serialBaudComboBox.currentIndex()]
                self.serialPara["dataBit"] = int(self.line3_dataBitComboBox.currentText())
                self.serialPara["chk"] = self.serialChk[self.serialChkCode[self.line3_checkComboBox.currentIndex()]]
                self.serialPara["stopBit"] = self.serialStopBitCode[self.line3_stopBitComboBox.currentIndex()]

                # 打開(kāi)串口
                self.serialPara["serialPt"] = serial.Serial()
                self.serialPara["serialPt"].baudrate = self.serialPara["baud"]
                self.serialPara["serialPt"].parity = self.serialPara["chk"]
                self.serialPara["serialPt"].stopbits = self.serialPara["stopBit"]
                self.serialPara["serialPt"].bytesize = self.serialPara["dataBit"]
                self.serialPara["serialPt"].port = self.serialPara["comNo"]

                self.serialPara["serialPt"].open()
                # 啟動(dòng)線(xiàn)程
                self.serialThread = ReceiveThread(self.serialPara["serialPt"], self.dispContent)
                self.serialThread.start()

            except Exception:
                QtWidgets.QMessageBox.information(self, "警告", "串口打開(kāi)失敗", QtWidgets.QMessageBox.Ok)
                return

                # print "端口號(hào): %d" % self.serialPara["comNo"]
        else:
            self.serialPara["serialPt"].close()
        self.setSerialState(not self.isSerialOpen)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    m = SerialFrame()
    #event = SerialOperate(m)
    m.show()
    app.exec_()



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末膀篮,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子岂膳,更是在濱河造成了極大的恐慌誓竿,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谈截,死亡現(xiàn)場(chǎng)離奇詭異筷屡,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)簸喂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)毙死,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人喻鳄,你說(shuō)我怎么就攤上這事扼倘。” “怎么了除呵?”我有些...
    開(kāi)封第一講書(shū)人閱讀 164,548評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵再菊,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我颜曾,道長(zhǎng)纠拔,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,657評(píng)論 1 293
  • 正文 為了忘掉前任泛豪,我火速辦了婚禮稠诲,結(jié)果婚禮上侦鹏,老公的妹妹穿的比我還像新娘。我一直安慰自己臀叙,他們只是感情好种柑,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,689評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著匹耕,像睡著了一般聚请。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上稳其,一...
    開(kāi)封第一講書(shū)人閱讀 51,554評(píng)論 1 305
  • 那天驶赏,我揣著相機(jī)與錄音,去河邊找鬼既鞠。 笑死煤傍,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嘱蛋。 我是一名探鬼主播蚯姆,決...
    沈念sama閱讀 40,302評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼洒敏!你這毒婦竟也來(lái)了龄恋?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,216評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤凶伙,失蹤者是張志新(化名)和其女友劉穎郭毕,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體函荣,經(jīng)...
    沈念sama閱讀 45,661評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡显押,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,851評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了傻挂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乘碑。...
    茶點(diǎn)故事閱讀 39,977評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖金拒,靈堂內(nèi)的尸體忽然破棺而出兽肤,到底是詐尸還是另有隱情,我是刑警寧澤殖蚕,帶...
    沈念sama閱讀 35,697評(píng)論 5 347
  • 正文 年R本政府宣布轿衔,位于F島的核電站,受9級(jí)特大地震影響睦疫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜鞭呕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,306評(píng)論 3 330
  • 文/蒙蒙 一蛤育、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦瓦糕、人聲如沸底洗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,898評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)亥揖。三九已至,卻和暖如春圣勒,著一層夾襖步出監(jiān)牢的瞬間费变,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,019評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工圣贸, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留挚歧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,138評(píng)論 3 370
  • 正文 我出身青樓吁峻,卻偏偏與公主長(zhǎng)得像滑负,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子用含,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,927評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容