Qt之圖形視圖框架

簡述

圖形視圖(Graphics View)提供了一個平臺,用于大量自定義2D圖元的管理與交互,并提供了一個視圖部件(view widget)來顯示可以縮放和旋轉的圖元。
框架包括一個事件傳播架構,支持場景(Scene)中的圖元(Item)進行精確的雙精度交互功能。圖元可以處理鍵盤事件、鼠標按下、移動、釋放和雙擊事件,同時也能跟蹤鼠標移動。
圖形視圖使用一個BSP(Binary Space Partitioning - 二叉空間分割)樹,以提供對圖形元素的快速查找,正因為如此,它可以使超大的場景實時地可視化,即使包含數百萬的圖元。

圖形視圖架構

圖形視圖提供了一個基于圖元的方式來實現模型視圖(model-view)編程,很像InterView中的便利類:QTableView、QTreeViewQListView。多個視圖可以觀察一個單獨的場景,場景則包含了不同的幾何形狀圖元 。

場景

QGraphicsScene提供了圖形視圖場景。
場景有以下職責:

  • 提供一個快速的接口,用于管理大量圖元
  • 向每個圖元傳遞事件
  • 管理圖元的狀態,如:選中、焦點處理
  • 提供未進行坐標轉換的渲染功能,主要用于打印

場景是QGraphicsItem對象的容器。調用QGraphicsScene::addItem()將圖元添加到場景中后,你就可以通過調用場景中的不同的查找函數來查找其中的圖元。QGraphicsScene::items()函數及其重載函數可以返回所有圖元,包括:點、矩形、多邊形、通用矢量路徑。
QGraphicsScene::itemAt()返回在特定點上最上面的圖元。所有找到的圖元按照層疊遞減的排列順序(即:最先返回的圖元是最頂層的,最后返回的則是最底層的)。

QGraphicsScene scene;
QGraphicsRectItem *rect = scene.addRect(QRectF(0, 0, 100, 100));

QGraphicsItem *item = scene.itemAt(50, 50);
// item == rect

QGraphicsScene的事件傳遞機制負責將場景事件傳遞給圖元,同時也管理圖元之間的傳遞。如果場景在某個位置得到一個鼠標按下事件,就將該事件傳遞給這個位置上的圖元。
QGraphicsScene同時還管理某些圖元的狀態,例如:圖元的選中和焦點。可以通過調用QGraphicsScene::setSelectionArea(),傳遞一個任意形狀,來選中場景中的圖元。此功能也被用于QGraphicsView中橡皮筋(rubberband)選中的基礎。通過調用QGraphicsScene::selectedItems()可以獲取當前選中的圖元列表。另外一種由QGraphicsScene處理的狀態是:一個圖元是否有鍵盤輸入焦點。你可以調用QGraphicsScene::setFocusItem()或QGraphicsItem::setFocus()為一個圖元設置焦點,或通過QGraphicsScene::focusItem()獲取當前的焦點圖元。
最后,QGraphicsScene允許通過QGraphicsScene::render()將部分場景繪制到繪圖設備(paint device - 例如:QImage、QPrinter、QWidget)上。可以在本文關于“打印”部分了解更多細節。

視圖

QGraphicsView提供了視圖部件,將一個場景中的內容顯示出來。你可以附加多個視圖到同一個場景,從而針對同一數據集提供幾個視口(viewport)。該視圖部件是一個滾動區域(scroll area),為大型場景瀏覽提供滾動條。如果要啟用OpenGL支持,可通過調用QGraphicsView::setViewport(),將一個QGLWidget設置為視口。

QGraphicsScene scene;
myPopulateScene(&scene);

QGraphicsView view(&scene);
view.show();

視圖通過鍵盤和鼠標接收輸入事件,并在事件發送給可視化的場景之前,將它們轉換成場景事件(將坐標轉化為適當的場景坐標)。
利用變換矩陣QGraphicsView::transform(),視圖可以轉換場景的坐標系,以便實現高級查看功能,例如:縮放、旋轉。為方便起見,QGraphicsView也提供了視圖和場景坐標之間轉換函數:QGraphicsView::mapToScene()和QGraphicsView::mapFromScene()。


view
圖元

QGraphicsItem是場景中圖元的基類。圖形視圖提供了一些典型形狀的標準圖元,例如:矩形 ( QGraphicsRectItem )、橢圓 ( QGraphicsEllipseItem ) 、文本項 ( QGraphicsTextItem )。但當你自定義圖元時,QGraphicsItem強大的特性就體現出來了。除此之外,QGraphicsItem還支持以下特性:

  • 鼠標按下、移動、釋放和雙擊事件,以及鼠標懸浮事件、滾輪事件和上下文菜單事件。
  • 鍵盤輸入焦點和鍵盤事件。
  • 拖放。
  • 分組:通過父子關系,或QGraphicsItemGroup。
  • 碰撞檢測。

和QGraphicsView一樣,處于局部坐標系下的圖元,也提供了很多函數用于圖元和場景之間、圖元到圖元的坐標映射。此外,和QGraphicsView一樣,它可以通過一個矩陣(matrix):QGraphicsItem::transform()來轉換其自身的坐標系,這對于旋轉和縮放單個圖元非常有用。
[圖片上傳中。。。(2)]

圖形視圖框架中的類

這些類提供了一種創建交互式應用程序的框架。

描述

QAbstractGraphicsShapeItem
所有路徑圖元的共同基類

QGraphicsAnchor
表示一個QGraphicsAnchorLayout中兩個圖元之間的anchor

QGraphicsAnchorLayout
布局可以anchor部件到圖形視圖中

QGraphicsEffect
所有圖形特效的基類

QGraphicsEllipseItem
可以添加到QGraphicsScene的橢圓圖元

QGraphicsGridLayout
圖形視圖中管理部件的網格布局

QGraphicsItem
QGraphicsScene中所有圖元的基類

QGraphicsItemGroup
一個將圖元組當做單個圖元來看待的容器

QGraphicsLayout
圖形視圖中所有布局類的基類

QGraphicsLayoutItem
可以被繼承,允許布局類管理的自定義圖元

QGraphicsLineItem
可以添加到QGraphicsScene的直線圖元

QGraphicsLinearLayout
圖形視圖中管理部件的水平或垂直布局

QGraphicsObject
所有需要信號、槽、屬性的圖元的基類

QGraphicsPathItem
可以添加到QGraphicsScene的路徑圖元

QGraphicsPixmapItem
可以添加到QGraphicsScene的圖形圖元

QGraphicsPolygonItem
可以添加到QGraphicsScene的多邊形圖元

QGraphicsProxyWidget
代理,用于將一個QWidget對象嵌入到QGraphicsScene中

QGraphicsRectItem
可以添加到QGraphicsScene的矩形圖元

QGraphicsScene
管理大量2D圖元的管理器

QGraphicsSceneContextMenuEvent
圖形視圖框架中的上下文菜單事件

QGraphicsSceneDragDropEvent
圖形視圖框架中的拖放事件

QGraphicsSceneEvent
所有圖形視圖相關事件的基類

QGraphicsSceneHelpEvent
Tooltip請求時的事件

QGraphicsSceneHoverEvent
圖形視圖框架中的懸停事件

QGraphicsSceneMouseEvent
圖形視圖框架中的鼠標事件

QGraphicsSceneMoveEvent
圖形視圖框架中的部件移動事件

QGraphicsSceneResizeEvent
圖形視圖框架中的部件大小改變事件

QGraphicsSceneWheelEvent
圖形視圖框架中的鼠標滾輪事件

QGraphicsSimpleTextItem
可以添加到QGraphicsScene的簡單文本圖元

QGraphicsSvgItem
可以用來呈現SVG文件內容的QGraphicsItem

QGraphicsTextItem
可以添加到QGraphicsScene的文本圖元,用于顯示格式化文本

QGraphicsTransform
創建QGraphicsItems高級矩陣變換的抽象基類

QGraphicsView
顯示一個QGraphicsScene內容的部件

QGraphicsWidget
QGraphicsScene中所有部件圖元的基類

QStyleOptionGraphicsItem
用于描述繪制一個QGraphicsItem所需的參數

圖形視圖坐標系

圖形視圖基于笛卡兒坐標系,場景中圖元的位置和幾何形狀由兩組數據來表示:X坐標和Y坐標。當使用一個未轉換的視圖來觀察一個場景,場景中的一個單元將會由場景上的一個像素表示。
注意 :圖形視圖使用了Qt的坐標系,不支持反轉的Y軸坐標系(即Y向上為正方向)。
圖形視圖中使用了三種有效的坐標系:圖元坐標、場景坐標、視圖坐標。為了簡化實現,圖形視圖提供了非常方便的函數來進行三個坐標系的映射。
渲染時,圖形視圖的場景坐標對應于QPainter的邏輯坐標,視圖坐標與設備坐標一致。參考:Coordinate System,了解更多關于邏輯坐標和設備坐標關系的內容。

圖形視圖坐標系

圖元坐標

圖元生活在自己的局部坐標系。它們的坐標通常圍繞它們的中心點(0, 0),并且這也是所有轉換的中心。圖元坐標系下的幾何元素通常指點、線或矩形。
創建自定義圖元時,只需考慮圖元坐標即可。QGraphicsScene和QGraphicsView會為你實現所有相關的轉換,這樣一來,實現自定義圖元就容易多了。例如:當你接收到鼠標按下或拖拽事件時,事件位置將由圖元坐標給出。如果某一點(傳遞一個圖元坐標作為參數)在圖元中,那么GraphicsItem::contains()虛函數將會返回true;否則,返回false。同樣的,項綁定的矩形或形狀區域也是項坐標系統的。同樣的,圖元的矩形邊界和形狀都是基于圖元坐標的。
圖元的位置是圖元的中心點在其父坐標系下的坐標,有時也被稱為父坐標。場景從這個意義上說是所有無父圖元的“parent”,頂層圖元的位置在場景坐標中。
子坐標是相對于父坐標而言的。如果子坐標沒有轉換,那么子坐標和父坐標的差異就和圖元在父坐標中的距離一樣。例如:一個未經轉換的子圖元正好位于父圖元的中心點,那么,這兩個圖元的坐標系是完全一樣的。如果子圖元的位置是(10, 0),那么子圖元的(0, 10)點就對應父圖元的(10, 10)點位置。
由于圖元的位置和轉換是相對于父圖元來說的,因此,雖然父圖元的轉換隱式地轉換了子圖元,但是子圖元的坐標不會因父圖元的轉換而受到影響。在上述示例中,即使父圖元經過了旋轉和縮放,子圖元的(0, 10)點始終對應父圖元的(10, 10)點。不過相對于場景來說,子圖元將隨著父圖元進行轉換和偏移 。如果父圖元縮放了(2x, 2x),那么子圖元在場景中的坐標是(20, 0),并且其(10, 0)點將會對應于場景中的(40, 0)點。
不管圖元或父圖元進行了怎樣的轉換,QGraphicsItem的函數操作都在圖元坐標內。例如:一個圖元的矩形邊界(QGraphicsItem::boundingRect())總是在圖元坐標下給出。但是QGraphicsItem::pos()是例外之一,該函數表示其在父圖元中的位置 。

場景坐標

場景為所有的圖元提供了基礎的坐標系。場景坐標系描述了每一個頂層圖元的位置,同時構成了從視圖傳遞到場景的所有場景事件的基礎。場景中的每個圖元都有一個場景位置和矩形邊界(QGraphicsItem::scenePos()、QGraphicsItem::sceneBoundingRect());另外,也有其自身的位置和矩形邊界。場景位置描述了圖元在場景坐標下內的位置,場景矩形邊界則提供給QGraphicsScene來決定場景中的哪塊區域已經被改變了。場景中的變化通過QGraphicsScene::changed()信號發出,參數是場景矩形列表。

視圖坐標

視圖坐標是部件的坐標,視圖坐標中的每個單位對應一個像素。對于該坐標系來說比較特殊的一點是:它相對于部件或視口,不會受被觀察的場景所影響。QGraphicsView的視口左上角總是(0, 0),右下角總是(viewport width, viewport height)。所有的鼠標事件和拖拽事件都以視圖坐標接收到的,你需要將這些坐標映射到場景,以便于和圖元進行交互。

坐標映射

通常處理場景中的圖元時,從場景到圖元、從圖元到圖元、從視圖到場景的坐標或任意形狀轉換將會非常有用。例如:當在QGraphicsView視口中點擊鼠標,你可以向場景詢問當前鼠標下方的是什么圖元(調用 QGraphicsView::mapToScene()轉換坐標,然后通過QGraphicsScene::itemAt()查詢圖元)。如果想知道一個圖元處于視口中的位置,可以調用圖元的函數QGraphicsItem::mapToScene(),然后再調用視圖的函數QGraphicsView::mapFromScene()。最后,如果想查找位于一個橢圓區域內的圖元,你可以把一個QPainterPath傳遞給mapToScene(),然后將轉換后的path傳遞給QGraphicsScene::items()。
通過調用QGraphicsItem::mapToScene()將坐標或任意形狀映射到圖元的場景中去,而調用QGraphicsItem::mapFromScene()將其映射回來;通過調用QGraphicsItem::mapToParent()將圖元映射到父圖元,而調用QGraphicsItem::mapFromParent()將其映射回來;甚至可以調用QGraphicsItem::mapToItem()和QGraphicsItem::mapFromItem()在不同的圖元間進行映射。所有的映射函數均支持點、矩形、多邊形和路徑。
在視圖和場景之間也存在著同樣的映射函數:QGraphicsView::mapFromScene()和QGraphicsView::mapToScene()。要從視圖映射到圖元,第一步是映射到場景,然后才能從場景映射到圖元。

主要特點

縮放和旋轉

和QPainter一樣,QGraphicsView也可以通過QGraphicsView::setMatrix()支持仿射轉換。通過將轉換應用到視圖上,可以很輕松地添加對普通瀏覽的支持,例如:縮放和旋轉。
下面的示例,說明了如何通過QGraphicsView子類來實現旋轉和縮放:

class View : public QGraphicsView
{
Q_OBJECT ...public slots: void zoomIn() { scale(1.2, 1.2); } void zoomOut() { scale(1 / 1.2, 1 / 1.2); } void rotateLeft() { rotate(-10); } void rotateRight() { rotate(10); } ...};

槽可以關聯到啟用了“autoRepeat”屬性的QToolButtons。
在轉換視圖過程中,QGraphicsView始終保持與視圖中心對齊。
參考:Elastic Nodes Example,了解更多關于縮放的內容。
打印
圖形視圖通過其渲染函數QGraphicsScene::render()和QGraphicsView::render(),提供了非常簡單的打印功能。
這兩個函數提供了相同的API:只需要將QPainter傳給繪制函數,就可以將場景或視圖的全部或部分內容渲染到任何繪圖設備上。
下面的示例展示了如何利用QPrinter將整個場景打印到整頁上:
QGraphicsScene scene;scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green));QPrinter printer;if (QPrintDialog(&printer).exec() == QDialog::Accepted) { QPainter painter(&printer); painter.setRenderHint(QPainter::Antialiasing); scene.render(&painter);}
1
2
3
4
5
6
7
8
9

1
2
3
4
5
6
7
8
9

場景和視圖繪制函數的區別在于:前者操作的是場景坐標,后者操作的則是視圖坐標。QGraphicsScene::render()多用于打印一個未轉換的場景各部分,例如:打印幾何數據圖表或文本文檔。 QGraphicsView::render()則比較適合用于抓取屏幕截圖,其缺省行為是使用提供的painter來渲染視口中確切的內容。
QGraphicsScene scene;scene.addRect(QRectF(0, 0, 100, 200), QPen(Qt::black), QBrush(Qt::green));QPixmap pixmap;QPainter painter(&pixmap);painter.setRenderHint(QPainter::Antialiasing);scene.render(&painter);painter.end();pixmap.save("scene.png");
1
2
3
4
5
6
7
8
9
10

1
2
3
4
5
6
7
8
9
10

當源區域和目標區域的大小不匹配時,源區域內容將會被縮放來適應目標區域。通過傳遞Qt::AspectRatioMode參數給你使用的渲染函數,在內容被縮放時,可以選擇保持或忽略場景的縱橫比。
拖放
由于QGraphicsView間接繼承了QWidget,因此QGraphicsView也提供了和QWidget一樣的拖放功能。此外,為方便起見,圖形視圖框架為場景、每個圖元提供了拖放支持。當視圖接收到一個拖拽動作,它將拖放事件轉換為一個QGraphicsSceneDragDropEvent,然后將其轉發給場景。場景則會接管該事件的調度,并將其發送給鼠標下面第一個接受放下動作的圖元。
要拖拽一個圖元,只需要創建一個QDrag對象,將指針傳給開始拖拽的部件。圖元可以同時被多個視圖觀察,但是只有一個視圖可以進行拖拽。在大多數情況下,拖拽都從鼠標按下或移動開始,因此在 mousePressEvent()或mouseMoveEvent()事件中,你可以從事件中拿到原始的部件指針,例如:
void CustomItem::mousePressEvent(QGraphicsSceneMouseEvent *event){ QMimeData *data = new QMimeData; data->setColor(Qt::green); QDrag *drag = new QDrag(event->widget()); drag->setMimeData(data); drag->start();}
1
2
3
4
5
6
7
8
9

1
2
3
4
5
6
7
8
9

要攔截場景中的拖放事件,需要實現QGraphicsScene::dragEnterEvent(),選擇你需要處理的事件,然后進行相應處理即可。你可以到 QGraphicsScene的文章中查看更多關于拖放的內容。
圖元通過調用QGraphicsItem::setAcceptDrops()來啟用對拖放的支持;如果要處理拖動,需要實現 QGraphicsItem::dragEnterEvent()、QGraphicsItem::dragMoveEvent()、QGraphicsItem::dragLeaveEvent()、QGraphicsItem::dropEvent(),這幾個事件。
參考:Drag and Drop Robot example,了解更多關于圖形視圖拖拽的內容。
光標和tooltip
和QWidget一樣,QGraphicsItem也支持設置光標(QGraphicsItem::setCursor())和tooltip(QGraphicsItem::setToolTip())。當鼠標光標進入item區域(由QGraphicsItem::contains()檢測)時,光標和tooltip就會被QGraphicsView激活。
你也可以通過調用QGraphicsView::setCursor(),直接為視圖設置一個默認的光標。
參考:Drag and Drop Robot example,了解更多關于tooltip和光標形狀操作的內容。
動畫
圖形視圖在幾個層面上提供了對動畫的支持。你可以用Animation Framework輕松地設置動畫:只需要讓你的圖元從QGraphicsObject繼承,然后將QPropertyAnimation綁定到上面。QPropertyAnimation可以為任何QObject屬性實現動畫效果。
另外一個選擇是:創建一個自定義圖元,從QObject和QGraphicsItem繼承。該圖元可以設置自己的定時器,然后在QObject::timerEvent()中控制動畫。
第三個選擇僅限于與Qt3中的QCanvas兼容。調用QGraphicsScene::advance()從而會依次調用 QGraphicsItem::advance()。
OpenGL渲染
要啟用OpenGL渲染,只要簡單地調用QGraphicsView::setViewport()來設置一個新的QGLWidget作為QGraphicsView的視口。如果你希望OpenGL具有反鋸齒,則需要OpenGL支持采樣緩沖(參考:QGLFormat::sampleBuffers())。
示例:
QGraphicsView view(&scene);view.setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
1
2

1
2

圖元組
通過將一個圖元設置為另一個圖元的子圖元,就可以得到圖元組最重要的功能:圖元會一起移動,所有轉換都會從父圖元傳播到子圖元中。
此外,QGraphicsItemGroup是一個特殊的圖元,它提供了對子圖元事件的支持,同時還提供了用于添加和刪除子圖元的接口。將一個圖元添加到QGraphicsItemGroup將保持圖元原始的位置和坐標轉換,不過重新設置圖元的父圖元則會導致圖元重新定位到相對于父圖元的位置。為了方便起見,你可以調用QGraphicsScene::createItemGroup()來創建QGraphicsItemGroup圖元。
部件和布局
Qt4.4通過QGraphicsWidget引入了對幾何體和對布局敏感的圖元的支持。這一特殊的基類圖元和QWidget類似,但是不像QWidget,它沒有從QPaintDevice繼承,而是從QGraphicsItem。這樣就允許你完全實現能夠處理事件、信號與槽、大小調整和策略的部件,同時你還可以通過QGraphicsLinearLayout和QGraphicsGridLayout來管理部件的幾何元素。
QGraphicsWidget
QGraphicsWidget建立在QGraphicsItem之上,具有QGraphicsItem的所有功能,保持了較小的資源占用,同時提供了兩者的優勢:來自QWidget的額外的功能,例如:樣式、字體、調色板、布局、幾何形狀,來自QGraphicsItem的分辨率獨立性和坐標轉換的支持。由于圖形視圖使用真實的坐標而不是整數,因此 QGraphicsWidget的幾何形狀函數可以同時操作QRectF和QPointF。同時也能應用到邊框的大小、邊距和間距上,例如:對于QGraphicsWidget,規定內容邊距為(0.5, 0.5, 0.5, 0.5)是非常常見的。例如:你可以創建子部件,甚至是“頂級”窗口。在某些情況下,你甚至可以將圖形視圖用于高級多文檔界面的應用程序。
QGraphicsWidget支持部分QWidget屬性,包括窗口標志位(window flags)和屬性,但是并非全部支持。可以參考QGraphicsWidget文檔,以獲取完整列表來判斷哪些支持以及哪些不支持。例如:你可以在創建QGraphicsWidget時賦予Qt::Window標志,從而得到封裝的窗口,但是圖形視圖目標并不支持 Qt::Sheet和Qt::Drawer標志,這兩者在Mac Os X上非常常見。
QGraphicsLayout
QGraphicsLayout是第二代布局框架的內容之一,專門為QGraphicsWidget設計。其API和QLayout非常相似。你可以在QGraphicsLinearLayout或QGraphicsGridLayout中對部件或者子布局進行管理,也可以通過派生QGraphicsLayout實現你自己的布局類,還可以通過派生QGraphicsLayoutItem來實現你自己的適配器,從而將QGraphicsItem圖元加入到布局中。
嵌入式部件支持
圖形視圖對將任何部件嵌入到場景中提供無縫的支持。你可以嵌入簡單的部件,例如:QLineEdit或QPushButton,也可以是復雜的部件,例如:QTabWidget,甚至是完整的主窗口。要將部件嵌入場景中,只需要簡單地調用QGraphicsScene::addWidget()或者創建一個QGraphicsProxyWidget對象并將部件手工的嵌入其中。
通過QGraphicsProxyWidget圖形視圖能夠完全繼承客戶端部件特性,包括:它的鼠標光標、tooltip、鼠標事件、平板電和鍵盤事件、子窗口、動畫、彈出(例如:QComboBox或QCompleter),以及部件的輸入焦點和激活狀態。QGraphicsProxyWidget甚至集成了嵌入式部件的tab切換順序,這樣你就可以通過tab鍵讓焦點進入或者移出嵌入式部件。你甚至可以嵌入一個新的 QGraphicsView到你的場景中,從而提供復雜的嵌套的視圖。
當改變一個嵌入式部件,圖形視圖可以確保部件轉換時與分辨率無關,當放大時使字體和樣式看起來干凈利落。(注意:分辨率無關的效果取決于風格。)
性能
浮點指令
為了精確和快速的將坐標轉換和特效應用到圖元上,圖形視圖在編譯的時候默認用戶的硬件能夠為浮點指令提供合理的性能。
很多工作站和桌面電腦都配備了適當的硬件來加速這種類型的計算,但是一些嵌入式設備可能僅僅提供了處理數學運算的庫,或者需要用軟件來模擬浮點指令。
這樣,在某些設備上,某些類型的特效可能要比預期的慢。有可能可以在其它方面進行優化來彌補性能上的損失,例如:用OpenGL來繪制場景。不過,如果優化本身是依賴于浮點計算硬件的話,可能都會帶來性能上的損失。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,647評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,914評論 2 372

推薦閱讀更多精彩內容