基于QTdesigner的PyQt编程

前面的教程中有讲过对于python自带的Tk模块的使用,实际上个人感觉Tk的使用不仅繁琐,而且做出来的界面并不美观,这里向大家推荐pyqt。
qyqt这个模块的最大优势在于界面可以使用qtdesigner直观的制作,然后代码直接读取就可以,省去了繁琐的排版等等步骤,而且界面的美观程度也是tk所无法达到的。
我个人比较喜欢qtdesigner制作界面,在qtdesigner上对界面进行修改,这样的话可以省去很多修改和调试的时间,当然如果你用qt熟练的话据说直接写代码的效率并不比用qtdesigner高,并且更灵活,这个就看个人喜好了。
用qtdesigner的时候最好在制作完界面后对界面进行布局,当然你不使用布局也是可以运行的,但是在别的电脑,分辨率不同的情况下会导致软件显示出问题,并且无法根据界面拉伸来解决。如果你布局过,那么可以使用界面的伸缩让界面自己重新排布。至于排版的方法就是选中你要布局的目标然后点击布局,在布局中你可以多运用Horizontal Spacer 和vertical spacer。一般我会一行一行进行水平布局之后再整体进行垂直布局。
首先你需要用qtdesigner制作一个ui界面,然后通过python代码进行界面的读取。

对于UI文件的可视化操作这里有两种办法:

第一种:直接在python文件上读取QTDesigner创建的UI文件
直接读取ui文件,假设我的ui文件名为"SL_manage.ui",那么我的python代码应该是:
#MainUi.py
from PyQt5 import QtWidgets, uic,QtCore,QtGui
import os
path = os.getcwd()
qtCreatorFile = path +os.sep+"ui"+os.sep+"SL_manage.ui"  # Enter file here.
Ui_MainWindow, QtBaseClass = uic.loadUiType(qtCreatorFile)
#_translate = QtCore.QCoreApplication.translate#
_translate = QtCore.QCoreApplication.translate这个主要用于后期的UI界面文字字体以及颜色便捷的更改
创建一个对象,该对象就是你的整个窗体:
class MainUi(QtWidgets.QMainWindow, Ui_MainWindow):
#这里的第一个变量是你该窗口的类型,第二个是该窗口对象。
#这里是主窗口类型。所以设置成当QtWidgets.QMainWindow。
#你的窗口是一个会话框时你需要设置成:QtWidgets.QDialog
   def __init__(self):
       QtWidgets.QMainWindow.__init__(self)
       Ui_MainWindow.__init__(self)
       self.setupUi(self)

至此,窗体对象已经创建完毕,接着,我们需要用一个函数取创建这个对象并将他显示出来,那么就需要下列代码:

#文件名: ShowUi.py
from PyQt5 import QtWidgets, uic,QtCore,QtGui

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = MainUi()   #创建窗体对象
    window.show()    #窗体显示
    sys.exit(app.exec_())   

如果你的程序还有新的窗口,你可以用同样的方法在继续写一个窗体对象,
然后在你的ShowUi.py中进行对象的创建,甚至于在我们的MainUi中创建也是可以的。

第二种办法是将UI文件直接转换成py文件:

将UI文件转化成python文件,然后进行相同的对象调用。方法实际上和前者是一样的,这里首先来说明一下如何转换ui文件:
我用的编译器是pycharm,在pycharm的工具栏类有个外部工具,你可以将指令填入外部工具,这样,你只需要将UI文件拖入pacharm然后运行你这个工具就可以自动生成python文件,这样可以省去反复敲指令的麻烦。配置如图:在工具栏的外部工具中。

pycharm配置.png
配置如图,名称:自定义。
程序栏写入python所在目录下的python.exe文件。参数则是:-m PyQt5.uic.pyuic  $FileName$ -o $FileNameWithoutExtension$.py
就是生成一个与当前操作文件相同名字的python文件。
工作目录则是$FileDir$,意思为当前文件所在目录

当然如果你不想使用这个工具,你就喜欢自己手动敲指令,那么你就打开你的cmd,或者终端,然后输入

python -m 路径+PyQt5.uic.pyuic  ui文件路径+名字 -o 输出的py文件路径加名字

到这里你就会生成一个python文件,但这个python文件实际上还是不能直接生成窗口的,需要你进行代码的可视化操作,操作方法如下:
假设我生成了一个叫"main_menu.py"的python文件,文件内容大抵为这样:

文件名:main_menu.py:
ui.jpg

在这里我们可以看到,这个python文件创建了一个叫UI_MainWindow的对象,这时你应该已经猜到了,这个对象正是我们所制作的界面,也就是说我们的UI文件被QT的一个组件翻译成了一个python对象。我们接下来所需要做的,就是在python文件中引用这个对象,引用方式如下:

#首先你需要在引用的python文件内导入该对象所在的文件,也就是main_menu.py
import main_menu   #导入该对象所在文件
Ui_MainWindow = main_menu.Ui_MainWindow#指定Ui_MainWindow 为main_menu文件下的Ui_MainWindow对象。

class CoperQt(QtWidgets.QMainWindow,Ui_MainWindow):#创建一个Qt对象
#这里的第一个变量是你该窗口的类型,第二个是该窗口对象。
#这里是主窗口类型。所以设置成当QtWidgets.QMainWindow。
#你的窗口是一个会话框时你需要设置成:QtWidgets.QDialog
    def __init__(self):
        QtWidgets.QMainWindow.__init__(self)  # 创建主界面对象
        Ui_MainWindow.__init__(self)#主界面对象初始化
        self.setupUi(self)  #配置主界面对象

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = CoperQt()#创建QT对象
    window.show()#QT对象显示
    sys.exit(app.exec_())

这样,你的python工程就可以脱离UI文件直接进行使用了,好处就是在打包成EXE文件的时候你不用给他搭配上UI文件。
关于Qt的操作我这里简单说几个比较常用而且典型的,如果需要深入那就需要你们你几查阅相关手册文档了,我对于这类工具基本就是够用就行,并不是我的主业:

按钮

按钮.png

按钮的触发在QT里用的是一个槽和信号的概念,这个概念我们实际上不用想的那么复杂,无非也就是将按钮的事件绑定一个函数,当事件触发,那么函数就运行,模板代码如下:

self.Button0.clicked.connect(self.start_find)  # button0的点击事件绑定start_find函数
关于绑定函数的传参除了可以使用全局变量还可以使用python的lambda,如我要传入x:
self.Button0.clicked.connect(command=lambda:button_process(x))

定时器

接着是Qt定时器,这个组件也特别实用,可以让你的界面定时的去执行某个函数,概念基本上就跟单片机的中断是一样的。
比如我在窗口显示一个时间,我需要他每一秒都更新窗口的时间信息,那么我就需要设置一个窗口定时器,代码如下:

    self.testTimer = QtCore.QTimer()  # 创建定时器
    self.testTimer.timeout.connect(self.show_time)  # 定时超时事件绑定show_time这个函数          
    self.testTimer.start(1000)          #定时器每一秒执行一次

下面是show_time这个函数

    def show_time(self):
        self.time_now = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))#

同理我们也可以把别的函数绑定到定时器上,让他定时运行。道理也是一样的

下拉选项栏配置

下拉选项栏.png

下拉选项栏在UI制作的时候也非常的常用,他的配置也不难,假设下拉选项栏是self.comboBox,代码如下:

选项栏有两个标识,一个是每一栏的编号index(从0开始),一个是每一栏的文本内容text:
    self.comboBox.insertItem(0, self.tr("None"))  # 第一个选项插入空
    self.comboBox.insertItem(0, "x") 第一个选项插入x字符
    self.comboBox.currentText() 读取选项栏文本:
    self.comboBox.currentIndex() 读取选项栏编号:
    self.comboBox.setCurrentIndex() 设置当前选项栏显示位置:(通过编号)
    self.comboBox.setCurrentText() 设置当前选项栏显示位置:(通过文本)
    self.comboBox.clear() 清空当前选项框内元素
    

这里有个小技巧,如何让选项栏选中后不用按按钮就触发事件。实际上就是运用到上面的定时器,你可以将定时器绑定上选项栏读取函数,这个函数每隔200MS或者1s读取选项栏的数值,这样,用户的只要更换选项立马能够做出反映。

会话窗:以下是最简单的会话窗代码:

header:会话窗标题
info:会话窗内容
def show_message(self,header = "说明",info = "无"):
        QtWidgets.QMessageBox.information(self,header,info,QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) 
# 使用infomation信息框             

#判断按键(显示两个按键,是和否)
QtWidgets.QMessageBox.Yes|QtWidgets.QMessageBox.No)
#确定按键(显示一个按键,OK)
# QtWidgets.QMessageBox.Ok

文件操作

文件操作的话实际上和TK基本类似,就是调用窗口来读取用户选取的文件路径以及名称,接着用户自己调用os函数去进行文件操作。
首先是打开文件,基本代码如下:

    def open_file(self):
        fileName1, filetype =QtWidgets.QFileDialog.getOpenFileName(self,
                                "请打开EXCEL文件", path,"Text Files (*.xlsx;*.xls)")  # 设置文件扩展名过滤,
        # 注意用双分号间隔
        if len(fileName1) == 0:
            return
        fileName1 = fileName1.replace('/', "\\")#win下需要进行文件分隔符转换
        my_excel = EasyExcel(filename=fileName1)#这是我自己写的excel读取程序这里创建一个excel读取对象
        self.data_list = my_excel.get_content()#读取excel的内容,返回是一个字典列表
        QtWidgets.QMessageBox.information(self,  # 使用infomation信息框
                                          "说明", "数据加载成功", QtWidgets.QMessageBox.Ok)
#会话窗提醒,数据读取成功

接下来是保存文件:

    def save_file(self):  #只是获取路径,实际保存需要调用OS模块
        fileName2, ok2 = QtWidgets.QFileDialog.getSaveFileName(self,
                            "文件保存","C:/","Text Files (*.xlsx);;Text Files (*.xls);;All Files (*)")
        #地址分隔符更改,QT获取的地址分隔符为/,而python为\\,需要替换
        if not fileName2:
            return
        fileName2 = fileName2.replace('/',"\\")
        #获取到文件路径,接下来的操作就需要你自己填写

表格

表格.png

表格作为一个可以输入和输出的组件,在做工具的时候也非常的实用,他的基本使用方法如下:

self.tableWidget.setHorizontalHeaderLabels(key_list)#设置表格表头数据
self.tableWidget.setColumnCount(x)           #设置表格的列数
self.tableWidget.setRowCount(x)           #设置表格的行数
self.tableWidget.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.ResizeToContents)   #表格设置成大小随内容改变
self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)  # 表格设置成只读
self.tableWidget.setSelectionBehavior(QTableWidget.SelectRows)#选择行
self.table.setSelectionMode(QTableWidget.SingleSelection)#选择单个行
self.tableWidget.setAlternatingRowColors(True)#隔行改变颜色
self.tableWidget.verticalHeader().sectionClicked.connect(self.VerSectionClicked)  # 表头单击信号
self.tableWidget.horizontalHeader().sectionClicked.connect(self.HorSectionClicked)  # 表头单击信号
self.tableWidget.rowCount()#返回表格的行数
self.tableWidget.columnCount()#返回表格的列数
self.tableWidget.item(row,clo ).text()#获取row行clo列的表格数据,从0开始
self.tableWidget.clear()#表格清空,不清空的话会永远残留
QTableWidget.clearContents() 只清除表项,不清除表头。
self.tableWidget.setItem(row,col, QTableWidgetItem("content"))#设置表格内容为字符串"content"
self.tableWidget.insertColumn(self, int column) 在某一列插入新的一列。
self.tableWidget.insertRow(self, int row)在某一行插入新的一行。
self.tableWidget.removeColumn(self, int column) 移除column列及其内容。
QTableWidget.removeRow(self, int row)移除第row行及其内容。
QTableWidget.setShowGrid(False)#不显示分割线
QTableWidget.hideRow(),hideColumn(),showRow(),showColumn()#隐藏相应的行或者列

如何在TableWidget内添加其他组件;下面额例程是讲timeEdit组件添加进TableWidget中

self.timeEdit = QtWidgets.QTimeEdit(Dialog)#创建一个timeEdit
self.tableWidget.setCellWidget(0, 0, self.timeEdit)#把timeedit添加进tableWidget内

单选框

单选框.png

单选框在实际中我们也经常用到,比如写一个软件的登陆界面的时候,单选框可以设置为自动登陆,记住密码等等
单选框的用法如下:

self.radioButton.clicked.connect(self.change_radio)  # 单选按钮选中绑定函数
self.radioButton.hide()  # 单选框2隐藏
self.radioButton.setChecked(True)#单选框选中,反之False
self.radioButton.isChecked()   #单选框是否选中,选中返回True反之False

单选框补充:
单选框这里要注意,就是单独的单选框并不能正常使用,假设我创建了个单选框用作记住密码按钮,实际上我点一下单选框则选中记住密码,但是再点一下他仍然是选中状态并不会取消,因为系统默认规定必须有且只有一个单选框被选中。所以这里教大家一个小诀窍,那就是多创建一个单选框,然后将它隐藏掉,这样就可以让两个交替被选中,从而达到点击选中,再点击取消的效果。
除此之外有个更好的办法就是不使用单选框,直接使用复选框

复选框.png

在QTdesigner里右键单选框选择变形为checkBox,则变成复选框,复选框和单选框的操作基本一样,唯一不同的是复选框可以允许一个界面上没有一个被选中,或者全部被选中,还有复选框是方形的,单选框是圆形的。

输入框

输入框主要用于人机交互中人的指令或者文本输入,他的基本操作方法是:


输入框.png
self.lineEdit.returnPressed.connect(self.check_info)  # 文本栏回车绑定函数
self.lineEdit.setEchoMode(QtWidgets.QLineEdit.Password)#设置成密码模式,也就是输入内容显示为实心的圆
self.lineEdit.setEchoMode(QtWidgets.QLineEdit.Normal)#设置成普通模式(默认)
self.lineEdit.setText(“hello world”)      # 设置输入文本
self.lineEdit.text()#返回输入框文本内容
self.lineEdit.show()#显示文本框
self.lineEdit.hide()#隐藏文本框
self.lineEdit.clear()#清空文本框

进度条

进度条.png

进度条一般会和定时器一起使用,用定时器绑定一个函数去获取进度然后再改变进度条的值,内容如下:

self.pbar.setValue(self.step)  #设置进度条进度 1则为1%

菜单栏

菜单栏主要功能无非就是绑定函数予以触发:

#Open_file是菜单栏内oepn_file这个按钮
self.Open_file.triggered.connect(self.open_file)

标题,标签

标签.png

标题标签主要用于软件上的文字标题或者描述

self.label.setText(
translate("MainWindow","<html><head/><body><p><span style="
                        "\" font-size:18pt; color:#0000ff;\">
{}
</span></p></body></html>"
).format(self.time_now))

标签补充:这里就说到了之前translate函数的作用,实际上因为我对QT不熟并且也没打算去多深入的学习,所以我在程序中更新Label的时候将原本在QTdesigner中设定的字体类型也直接复制过来,写入这个函数,不然你直接使用setText函数之后你会发现原来设置的字体格式全部会变成默认,当然你也可以不用translate函数,直接使用pyqt5内置的字体修改函数来修改。

timeEdit&&dateEdit&&datetimeEdit

self.timeEdit.setDisplayFormat('hh:mm')#设置时间格式
now_day = time.strftime("%Y-%m-%d", time.localtime())
self.dateEdit.setDate(QDate.fromString(now_day, 'yyyy-MM-dd'))
time = QtCore.QTime.toString(self.timeEdit.time(),"hh:mm")#获取时间便转化成字符串
now_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
self.dateTimeEdit.setDateTime(QDateTime.fromString(now_time, 'yyyy-MM-dd hh:mm:ss'))#
time = int(QtCore.QDateTime.toTime_t(self.dateTimeEdit.dateTime()))#获取时间并转化成时间戳
self.dateTimeEdit.setDateTime(QtCore.QDateTime.fromTime_t(时间戳))#通过时间戳设置timeedit显示的时间
self.dateTimeEdit.setMaximumDateTime(QtCore.QDateTime(QtCore.QDate(2106, 2, 7), QtCore.QTime(14, 28, 15)))#设置最大时间

在pyqt内创建一个线程

pyqt编程下经常会用到线程,因为有些耗时的操作,如果不放入线程中,则会引发qt界面的刷新卡顿,甚至没有反应。
(在这里友情提醒一下,多线程你也可以用python自带的thread模块做,但是因为gil锁,实际上只会用单核。但是qthread是用c++实现的,所以实际推荐用qthread来写多线程(如果条件允许))


class newThread(QtCore.QThread):
    def __init__(self,parent=None):
        super(readThread, self).__init__(parent)

    def run(self):
        while True:
            print("hello")
            time.sleep(10)
#如上操作创建了一个newThread的线程,
工作是每十秒打印一个hello。
当然如果想让线程开启,则需要在qt主程序内进行如下操作:

self.new_thread = newThread()  #创建线程对象
self.new_thread.start()  #开启。
#开启后你的qt就会起一个线程,
并且跑在run的while循环以内。
如果你想要中断这个线程。
那么就可以用标志位的形式从while(1)里面break出来。

在qt内给线程添加回调函数

def updateFigure():
    try:
        GetLastStatus = getLastStatus()#
        GetLastStatus.finished_signal.connect(success)#回调绑定成功函数
        GetLastStatus.error_signal.connect(error)#回调绑定失败函数
        GetLastStatus.start()#程序开始
    except Exception as e:
        print(e)

def success()
    print("Success")

def error()
    print("error")

class getLastStatus(QThread):
    finished_signal = pyqtSignal(str)#创建完成信号
    error_signal = pyqtSignal(str)#创建错误信号
    def __init__(self, parent=None):
        super().__init__(parent)
     
    def run(self):#重写内置运行函数
        if self._test() == True:
            self.finished_signal.emit('done')
            #如果完成,发送完成信号
        else:
            self.error_signal.emit("error")
            #如果出错,发送出错信号

    def _test(self):
        #return True
          return False

在pyqt内嵌Matplotlib

首先创建一个名为MatplotMenu的UI文件,在该文件内添加一个QFrame组件,然后创建一个LineEdit和两个Button。效果如下图所示。然后,用上述的办法,将他生成PY文件。


image.png

接着,创建一个名为MatplotObject.py的文件,填入如下代码。

from  PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import Ui.MatplotMenu as MatplotMenu #UI目录下的MatplotMenu
import matplotlib
matplotlib.use("Qt5Agg")  # 声明使用QT5
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.dates as mdate
import datetime

Ui_MainDialog = MatplotMenu.Ui_Dialog


class MatplotMenu(QDialog,Ui_MainDialog):#创建一个会话框对象
    def __init__(self):
        super(MatplotMenu,self).__init__(parent)
        self.title = 'Matplot测试'#设置窗体title
        self.setupUi(self)
        self._createCanvas()#创建画布
        self._createLayouts()#配置组件
        self.show()#显示组件
        self._updateFigure()#更新曲线图
        self.timer = QTimer(self)#创建定时更新定时器
        self.timer.timeout.connect(self._updateFigure)#绑定更新函数        
        self.pushButton_2.clicked.connect(self._reFresh)#按钮2绑定开始更新函数

    def closeEvent(self, event):#重写会话框关闭信号产生函数
        reply = QMessageBox.question(self, 'Message',
                                     "Are you sure to quit?", QMessageBox.Yes, QMessageBox.No)#产生提醒会话界面
        if reply == QMessageBox.Yes:#如果确认
            if self.timer.isActive():#定时器激活状态
                self.timer.stop()#停止定时器
                print("停止定时器")
            else:
                print("无需停止定时器")
            event.accept()#关闭事件接受
        else:
            event.ignore()#舍弃关闭事件

    def _reFresh(self):#刷新按钮绑定函数
        if self.timer.isActive() == True:#如果定时器激活状态
            self.timer.stop()#关闭定时器
            self.pushButton_2.setText("实时更新")#设置按钮字符
            print("关闭定时器......")
        else:
            self._updateFigure()#刷新界面
            self.timer.start(30000)#开启定时器
            self.pushButton_2.setText("暂停更新")#设置按钮字符
            print("打开定时器......")

    def _updateFigure(self):
        try:
            self._showLine()#显示曲线
        except Exception as e:
            print(e)

    def _showLine(self):
        self._canvas.refreshLine()

    def _errorProcess(self):
        pass

    def _createCanvas(self):
        self.setWindowTitle(self.title)#设置title
        # self.setGeometry(self.left, self.top, self.width, self.height)
        self._canvas = PlotCanvas(self, width=5, height=4)#创建matplot对象

    def _createLayouts(self):
        layout = QHBoxLayout(self.frame)#选定frame组件
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self._canvas) # 添加matplot对象到QT组件内,这是最重要的一个函数,用于将matplotlib和qt绑定

class PlotCanvas(FigureCanvas):#创建一个matplot对象
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        self._Font = {
            'family': 'SimHei',
            'weight': 'bold',
            'size': 15}
        fig = Figure(figsize=(width, height), dpi=dpi)
        FigureCanvas.__init__(self, fig)
        self.setParent(parent)
        FigureCanvas.setSizePolicy(self,QSizePolicy.Expanding,QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)
        self._ax = self.figure.add_subplot(111)

    def refreshLine(self):
        x = [];y = []#这里自行创建数据
        try:
            self._ax.plot(x,y, '--r*', label="Matplot Test")#绘图
            self._ax.set_title('Matplot Test', fontdict=self._Font)
            self._ax.set_xlabel("X轴", fontdict=self._Font)
            self._ax.set_ylabel("Y轴", fontdict=self._Font)
            self._ax.xaxis.grid(True, which='major')  # x坐标轴的网格使用主刻度
            self._ax.yaxis.grid(True, which="major")
            self.draw()
        except Exception as e:
            print(e)
    def plot(self):
        import datetime
        price_list = [
            {
                "PRICE" : "0.0",
                "Time" : "2018-01-22 18:56:00"},
            {
                "PRICE": "0.16461536288261414",
                "Time": "2018-01-22 20:07:18"
            },
            {
                "PRICE": "0.0",
                "Time": "2018-01-22 20:19:30"
            },
            {
                "PRICE": "0.01397849153727293",
                "Time": "2018-01-22 20:31:50"
            }
                    ]
        Font = {'family': 'SimHei',
                'weight': 'bold',
                'size': 15}
        x = []
        y = []  # 定义两个列表
        for item in price_list:  # 逐年取出单年所有信息
            y.append(float(item["PRICE"]))  # 价格数值加入y列表
            x.append(datetime.datetime.strptime(item["Time"], "%Y-%m-%d %H:%M:%S"))
            # print(type(datetime.datetime.strptime(item["Time"], "%Y-%m-%d %H:%M:%S")))

        self._ax = self.figure.add_subplot(111)
        self._ax.plot(x,y, '--r*',label = "NH3")
        self._ax.set_title('测试曲线图',fontdict = self._Font)
        self._ax.set_xlabel("时间(\"年-月-日 小时:分:秒\")",fontdict=self._Font)
        self._ax.set_ylabel("价格($)",fontdict=self._Font)
        self._ax.xaxis.set_major_formatter(mdate.DateFormatter('%Y-%m-%d %H:%M:%S'))
        self._ax.xaxis.grid(True, which='major')  # x坐标轴的网格使用主刻度
        self._ax.yaxis.grid(True, which="major")
        # self._ax.xaxis.set_xticklabels(rotation=75)
        # for label in self._ax.get_xticklabels() + self._ax.get_yticklabels():
        #     label.set_fontsize(6)
            # label.set_bbox(dict(facecolor='green', edgecolor='None', alpha=0.7))

        # self._ax.xticklabels(rotation=75)
        # self.xticks(rotation=75)
        self.draw()

if __name__ == "__main__":
    import sys
    app =QApplication(sys.argv)
    window = App()#创建QT对象
    window.show()#QT对象显示
    sys.exit(app.exec_())
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,306评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,657评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,928评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,688评论 0 220
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,105评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,024评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,159评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,937评论 0 212
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,689评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,851评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,325评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,651评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,364评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,192评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,985评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,154评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,955评论 2 279

推荐阅读更多精彩内容