用 C++ 和 libgd 來繪圖

用 C++ 和 libgd 來繪圖

[TOC]

舊文轉(zhuǎn)貼, 代碼很久以前寫的, 大約至今有十年了, 最近看到有人問如何用 C++ 來生成圖表.
有一個 graphviz 的開源庫可以用, 它用了自己的領(lǐng)域特定語言 DSL: dot 來生成圖表, 具體應(yīng)用可見 http://graphviz.org/

當(dāng)然也可以不用這么重的開源庫, 這里介紹了以前寫的一個chart 庫, 幾百行代碼, 采用了比較原始的作法, 調(diào)用了 libgd 基礎(chǔ)API, 如畫點, 畫線等原子方法來繪制圖表, 可以應(yīng)用于一些比較簡單的場合

實例

先看看生成的圖表實例

折線圖和魚骨頭圖

這里寫圖片描述

圓餅圖和直方圖

這里寫圖片描述

示例代碼

上面兩個圖表由以下幾十行代碼來實現(xiàn)

#include "TinyUtil.h"
#include "TinyChart.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory>


int main(int argc, char **argv)
{
    printf("-- write image by gd ---");
    {
        STR_VEC xScales;
        xScales.reserve(10);
        xScales.push_back("11-09");
        xScales.push_back("11-10");
        xScales.push_back("11-11");
        xScales.push_back("11-12");
        xScales.push_back("11-13");
        xScales.push_back("11-14");
        xScales.push_back("11-15");
        xScales.push_back("11-16");
        xScales.push_back("11-17");
        xScales.push_back("11-18");
        xScales.push_back("11-19");
        xScales.push_back("11-20");
        xScales.push_back("11-21");
        xScales.push_back("11-22");

        INT_VEC yScales;
        yScales.reserve(10);
        yScales.push_back(200);
        yScales.push_back(130);
        yScales.push_back(3456);
        yScales.push_back(2345);
        yScales.push_back(1320);
        yScales.push_back(30);
        yScales.push_back(2200);
        yScales.push_back(1330);
        yScales.push_back(3330);
        yScales.push_back(332);
        yScales.push_back(788);
        yScales.push_back(200);
        yScales.push_back(13890);
        yScales.push_back(200);

        TinyTrendlineDiagram* pt = new TinyTrendlineDiagram(
                "latency_trendline.png", 800, 250);
        pt->SetTitle("Trend of Latency (the middle network latency is the value of 0 coordinate)");
        pt->SetLabels(xScales);
        pt->SetValues(yScales);

        pt->Draw();
        pt->WriteImage();
        delete pt;
    }

    {
        STR_VEC xScales;
        xScales.push_back("America");
        xScales.push_back("China");
        xScales.push_back("Japan");
        xScales.push_back("England");
        xScales.push_back("France");
        xScales.push_back("Germany");
        xScales.push_back("South Korean");
        xScales.push_back("India");

        INT_VEC yScales;
        yScales.push_back(4800);
        yScales.push_back(3008);
        yScales.push_back(100);
        yScales.push_back(20);
        yScales.push_back(2000);
        yScales.push_back(178);
        yScales.push_back(258);
        yScales.push_back(1789);

        TinyDistributionDiagram* pd = new TinyDistributionDiagram(
                "users_distribution.png", 800, 600);
        pd->SetTitle("Daily active users distribution among the countries");
        pd->SetLabels(xScales);
        pd->SetValues(yScales);
        pd->Draw();
        pd->WriteImage();
        delete pd;
    }
    return 0;
}

?設(shè)計與實現(xiàn)

其實, 也就是封裝了libgd 的原子操作, 繪制了基本的圖形單元

?1) 首先下載并編譯依賴庫 libgd

  • 下載: Download libgd-2.2.1.tar.gz
  • 解壓: tar xvfz libgd-2.2.1.tar.gz
  • 構(gòu)建步驟 build steps
    cd libgd-2.2.1
    mkdir bld
    cd bld
    cmake -DENABLE_PNG=1 -DENABLE_JPEG=1 -DENABLE_FREETYPE=1 ..
    make
    make install
  1. 然后實現(xiàn)上圖所示的類, 加上測試, 約有千余行代碼, 放在 github 里

https://gist.github.com/walterfan/b7200fd3e5315ec1e16551fca096a67e

附以上類圖的源碼, 由 http://yuml.me 生成

// Cool Class Diagram
[Sharp]^[Arc]
[Arc]^[Eclipse]
[Arc]^[Circle]
[Sharp]^[Rectangle]
[Sharp]^[Scale]
[Sharp]^[Chart]
[Chart]^[CurveChart]
[Chart]^[ColumnChart]
[Chart]^[PieChart]
[Chart]^[HistogramChart]
[Diagram]-[note:Aggregate chart{bg:wheat}]
[Diagram]^[DistributionDiagram]
[Diagram]^[TrendlineDiagram]
[TrendlineDiagram]<>-0..*>[CurveChart]
[TrendlineDiagram]<>-0..*>[ColumnChart]
[DistributionDiagram]<>-0..*>[PieChart]
[DistributionDiagram]<>-0..*>[HistogramChart]

接口如下, 代碼比較老, 歡迎指正


#include <iostream>
#include <vector>
#include <string>
#include <map>

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>

#include "gd.h"
#include "gdfonts.h"
#include "gdfontt.h"

using namespace std;  

#define TinyPoint gdPoint
#define TinyFont gdFont
#define TinyColor int
#define WHITE 255,255,255
#define BLACK 0,0,0
#define GRAY 192,192,192
#define RED 255,0,0
#define GREEN 0,255,0
#define BLUE 0,0,255
#define MAGENTA 255,0,255
#define CYAN 0,255,255
#define YELLOW 255,255,0
#define AZURY 153,153,255
#define ORANGE_RED  255,36,00

#define PI 3.14159265357989

#ifdef NDEBUG
#define TRACE(msg)
#else
#define TRACE(msg)  cout<<__FILE__<<", "<<__LINE__<<": "<<msg<<endl;
#endif

typedef map<string, int, less<string>, allocator<int> > STR2INT_MAP;
typedef vector<int, allocator<int> > INT_VEC;
typedef vector<string, allocator<string> > STR_VEC;

const int NAMESIZE=256;
const int DAYS=14;

class TinyShape
{
public:
    TinyShape(gdImagePtr im)
    {
        m_pImage=im;
        m_nBorderWidth=1;
        SetBgColor(WHITE);
        SetFrColor(BLACK);
        SetBorderColor(BLACK);
        m_nBorderWidth=1;
    };
    void SetBgColor(int r,int g,int b)
    {
        m_BgColor=gdImageColorAllocate(m_pImage, r, g, b);
    };
    void SetFrColor(int r,int g,int b)
    {
        m_FrColor=gdImageColorAllocate(m_pImage, r, g, b);
    };

    void SetBorderColor(int r,int g,int b)
    {
        m_BorderColor=gdImageColorAllocate(m_pImage, r, g, b);
    };
    void SetBgColor(TinyColor color)
    {
        m_BgColor=color;
    };
    TinyColor GetBgColor()
    {
        return m_BgColor;
    };
    TinyColor GetBorderColor()
    {
        return m_BorderColor;
    };
    void SetFrColor(TinyColor color)
    {
        m_FrColor=color;
    };

    void SetBorderColor(TinyColor color)
    {
        m_BorderColor=color;
    };
    void SetBorderWidth(int w)
    {
        m_nBorderWidth=w;
    };
    virtual ~TinyShape()
    {
        m_pImage=NULL;
    };
    virtual void Draw() = 0;

    virtual void Fill() { };
protected:
    int m_nBorderWidth;
    gdImagePtr m_pImage;
    TinyColor m_BorderColor;
    TinyColor m_BgColor;
    TinyColor m_FrColor;
};

class TinyScale:public TinyShape
{
public:
    TinyScale(gdImagePtr im,TinyColor color):TinyShape(im)
    {
        m_FrColor=color;
        m_pFont=gdFontSmall;//gdFontTiny
        m_TopLeftPoint.x=0;
        m_TopLeftPoint.y=0;
        m_OffsetPoint.x=0;
        m_OffsetPoint.y=0;

    };
    void Draw()
    {
        gdImageString(m_pImage, m_pFont, m_TopLeftPoint.x+m_OffsetPoint.x, m_TopLeftPoint.y+m_OffsetPoint.y, (unsigned char*)m_text, m_FrColor);
    };
    void Draw(char * text)
    {
        TRACE(" TinyScale:Draw(char * text): " <<m_TopLeftPoint.x<<", "<<m_TopLeftPoint.y<<","<<text);
        gdImageString(m_pImage, m_pFont, m_TopLeftPoint.x+m_OffsetPoint.x, m_TopLeftPoint.y+m_OffsetPoint.y, (unsigned char*)text, m_FrColor);
    };
    void SetPosition(int x,int y)
    {
        m_TopLeftPoint.x=x;
        m_TopLeftPoint.y=y;
    };
    void SetOffset(int x,int y)
    {
        m_OffsetPoint.x=x;
        m_OffsetPoint.y=y;
    };
    void SetText(const char * text)
    {
        strncpy(m_text,text,10);
    };
    void SetFont(gdFontPtr font)
    {
        m_pFont=font;
    };
    TinyScale(gdImagePtr im,int x,int y):TinyShape(im)
    {
        m_TopLeftPoint.x=x;
        m_TopLeftPoint.y=y;
        SetFrColor(BLACK);
        m_pFont=gdFontSmall;
        m_OffsetPoint.x=0;
        m_OffsetPoint.y=0;
    };
    virtual ~TinyScale()
    {};
public:
    TinyPoint m_TopLeftPoint;
    TinyPoint m_OffsetPoint;
    char m_text[10];
private:
    gdFontPtr m_pFont;
};

class TinyRectangle:public TinyShape
{
public:
    TinyRectangle(gdImagePtr im,int x1,int y1,int x2,int y2):TinyShape(im)
    {
        SetSize(x1,y1,x2,y2);
    };
    TinyRectangle(gdImagePtr im):TinyShape(im)
    {

    };
    virtual ~TinyRectangle(){};

    TinyPoint m_TopLeftPoint;
    TinyPoint m_BottomRightPoint;

    void SetSize(int x1,int y1,int x2,int y2)
    {
        m_TopLeftPoint.x=x1;
        m_TopLeftPoint.y=y1;
        m_BottomRightPoint.x=x2;
        m_BottomRightPoint.y=y2;
    };
    void Draw()
    {
        gdImageRectangle(m_pImage,m_TopLeftPoint.x,m_TopLeftPoint.y,\
                        m_BottomRightPoint.x,m_BottomRightPoint.y,m_BorderColor);
    };
    void Fill()
    {
        //gdImageFilledRectangle(m_pImage,m_TopLeftPoint.x,m_TopLeftPoint.y,\
        //              m_BottomRightPoint.x,m_BottomRightPoint.y,m_BgColor);
        int x=(m_TopLeftPoint.x+m_BottomRightPoint.x)/2;
        int y=(m_TopLeftPoint.y+m_BottomRightPoint.y)/2;
        gdImageFillToBorder(m_pImage,x,y,m_BorderColor,m_BgColor);
    };
};
class TinyArc:public TinyShape
{
public:
    TinyArc(gdImagePtr im,int x,int y):TinyShape(im)
    {
        SetCentre(x,y);
        SetAngel(0,0);
        SetSize(0,0);
    };
    TinyArc(gdImagePtr im):TinyShape(im)
    {
    };
    virtual ~TinyArc()
    {};

    TinyPoint GetCentre() {
        return m_Centre;
    }

    void SetCentre(int x,int y)
    {
        m_Centre.x=x;
        m_Centre.y=y;
    };

    void SetAngel(float start,float end)
    {
        m_nStartAngle=start;
        m_nEndAngle=end;
    };

    void SetSize(int w,int h)
    {
        m_nWidth=w;
        m_nHeight=h;
    };
    void Draw()
    {
        gdImageArc(m_pImage,m_Centre.x,m_Centre.y,m_nWidth,m_nHeight,(int)ceil(m_nStartAngle),(int)ceil(m_nEndAngle),m_BorderColor);
    };
    void Fill()
    {
        gdImageFillToBorder(m_pImage,m_Centre.x,m_Centre.y,m_BorderColor,m_BgColor);
    };
    void Fill(TinyColor bordercolor,TinyColor bgcolor)
    {
        gdImageFillToBorder(m_pImage,m_Centre.x,m_Centre.y,bordercolor,bgcolor);
    };
protected:
    TinyPoint m_Centre;
    int m_nWidth;
    int m_nHeight;
    float m_nStartAngle;
    float m_nEndAngle;
};


class TinyCircle:public TinyArc
{
public:
    TinyCircle(gdImagePtr im,int x,int y,int r):TinyArc(im,x,y)
    {
        SetRadius(r);
        m_nStartAngle=0;
        m_nEndAngle=360;
    };
    TinyCircle(gdImagePtr im):TinyArc(im)
    {
    };
    void SetRadius(int r)
    {
        m_Radius=r;
        m_nWidth=2*r;
        m_nHeight=2*r;
    };
    virtual ~TinyCircle()
    {};
private:
    int m_Radius;
};

class TinyEclipse:public TinyArc
{
public:
    TinyEclipse(gdImagePtr im,int x,int y,int r):TinyArc(im,x,y)
    {
        SetRadius(r);
        m_nStartAngle=0;
        m_nEndAngle=0;
    };
    TinyEclipse(gdImagePtr im):TinyArc(im)
    {
    };
    void SetRadius(int r)
    {
        m_Radius=r;
        m_nWidth=2*r;
        m_nHeight=2*r;
    };

    void Draw()
    {
        float fAngle=m_nEndAngle-m_nStartAngle;
        if(fAngle<1)
            return;
        m_Points[0].x=m_Centre.x;
        m_Points[0].y=m_Centre.y;
        m_Points[1].x=m_Centre.x+(int)ceil(m_Radius*cos(m_nStartAngle*PI/180));
        m_Points[1].y=m_Centre.y-(int)ceil(m_Radius*sin(m_nStartAngle*PI/180));
        m_Points[2].x=m_Centre.x+(int)ceil(m_Radius*cos(m_nEndAngle*PI/180));
        m_Points[2].y=m_Centre.y-(int)ceil(m_Radius*sin(m_nEndAngle*PI/180));

        gdImageLine(m_pImage,m_Points[0].x,m_Points[0].y,m_Points[1].x,m_Points[1].y,m_BorderColor);
        gdImageLine(m_pImage,m_Points[0].x,m_Points[0].y,m_Points[2].x,m_Points[2].y,m_BorderColor);
    };
    void Fill()
    {
        int nAngle=(int)ceil(m_nEndAngle-m_nStartAngle);
        int x,y;
        TRACE("Angle: "<<m_nStartAngle<<"-"<<m_nEndAngle<<"="<<nAngle);
        if(nAngle<1)
            return;
        else if(nAngle<=10)
        {
            x=(m_Points[0].x+(m_Points[1].x+m_Points[2].x)/2)/2;
            y=(m_Points[0].y+(m_Points[1].y+m_Points[2].y)/2)/2;
        }
        else if(nAngle<=180)
        {
            x=(m_Points[1].x+m_Points[2].x)/2;
            y=(m_Points[1].y+m_Points[2].y)/2;
        }
        else
        {
            x=2*m_Centre.x-(m_Points[1].x+m_Points[2].x)/2;
            y=2*m_Centre.y-(m_Points[1].y+m_Points[2].y)/2;
        }
        TRACE("see "<<x<<","<<y);

        //gdImageFillToBorder(m_pImage,x,y,m_BgColor,m_BorderColor);
        gdImageFill(m_pImage,x,y,m_BgColor);
        //gdImageFilledPolygon(m_pImage, m_Points, 3, m_BgColor);

    };
    virtual ~TinyEclipse()
    {};
private:
    int m_Radius;
    TinyPoint m_Points[3];
};

class TinyChart:public TinyShape
{
protected:
    TinyColor m_FrameColor;
    TinyColor m_GridColor;
    TinyColor m_TitleColor;
    char m_szTitle[NAMESIZE];
    int m_nGridWidth;
    int m_nShapeWidth;

    TinyPoint m_TopLeftPoint;
    TinyPoint m_BottomRightPoint;
    TinyPoint m_FrameTopLeftPoint;
    TinyPoint m_FrameBottomRightPoint;

    int m_nLeftMargin;
    int m_nRightMargin;
    int m_nTopMargin;
    int m_nBottomMargin;

    int GetBigerScale(int nScale);

public:
    TinyChart(gdImagePtr im):TinyShape(im)
    {
        SetGridColor(BLACK);
        SetFrameColor(GRAY);
        SetTitleColor(AZURY);
        m_nGridWidth=1;
        m_nShapeWidth=10;
        m_nLeftMargin=0;
        m_nRightMargin=0;
        m_nTopMargin=0;
        m_nBottomMargin=0;
        strncpy(m_szTitle,"",NAMESIZE);

    };
    virtual ~TinyChart()
    {
        for(int i = 0;i<m_Shapes.size();i++)
            delete m_Shapes[i];
        m_Shapes.clear();

        for(int j = 0;j<m_xScale.size();j++)
            delete m_xScale[j];
        m_xScale.clear();

        for(int k = 0;k<m_yScale.size();k++)
            delete m_yScale[k];
        m_yScale.clear();
    };


    void SetPosition(int x1,int y1,int x2,int y2)
    {
        m_TopLeftPoint.x=x1;
        m_TopLeftPoint.y=y1;
        m_BottomRightPoint.x=x2;
        m_BottomRightPoint.y=y2;
    }

    void SetMargin(int top,int bottom,int left,int right)
    {
        m_nLeftMargin=left;
        m_nRightMargin=right;
        m_nTopMargin=top;
        m_nBottomMargin=bottom;
    }
    void SetShapeWidth(int width)
    {
        m_nShapeWidth=width;
    };
    void SetGridColor(int r,int g,int b)
    {
        m_GridColor=gdImageColorAllocate(m_pImage, r, g, b);
    };
    void SetTitleColor(int r,int g,int b)
    {
        m_TitleColor=gdImageColorAllocate(m_pImage, r, g, b);
    };
    void SetFrameColor(int r,int g,int b)
    {
        m_FrameColor=gdImageColorAllocate(m_pImage, r, g, b);
    };

    virtual void SetVerticalScale(INT_VEC& vecYScale){};
    virtual void SetHorziontalScale(STR_VEC& vecXScale);
    //virtual void SetData(){};
    virtual void SetTitle(char* title);

    virtual void Plot(){};
    virtual void DrawTitle();
    virtual void DrawGrid();

    void DrawFrame();
    void DrawBorder();

    void Draw();
protected:
    INT_VEC m_nData;
    vector<TinyShape*> m_Shapes;
    vector<TinyScale*> m_xScale;
    vector<TinyScale*> m_yScale;
    int m_nVerticalScale;
    int m_nHorziontalScale;
};

class TinyCurveChart:public TinyChart
{
public:
    void Plot();
    //void SetData();
    void SetVerticalScale(INT_VEC& vecYScale);
    //void SetHorziontalScale(STR_VEC& vecXScale,int nXScale){};
    TinyCurveChart(gdImagePtr im):TinyChart(im)
    {
        SetFrColor(RED);
    };
    virtual ~TinyCurveChart()
    {};
    void DrawTitle(){};
};

class TinyColumnChart:public TinyChart
{
public:
    void Plot();
    void SetVerticalScale(INT_VEC& vecYScale);
    //void SetHorziontalScale(STR_VEC& vecXScale,int nXScale){};
    TinyColumnChart(gdImagePtr im):TinyChart(im)
    {};
    virtual ~TinyColumnChart()
    {};
};
class TinyHistogram:public TinyChart
{
public:
    void Plot();
    void SetHorziontalScale(STR_VEC& vecXScale);
    void SetVerticalScale(INT_VEC& vecYScale);
    //void SetHorziontalScale(STR_VEC& vecXScale,int nXScale){};
    TinyHistogram(gdImagePtr im):TinyChart(im)
    {};
    virtual ~TinyHistogram()
    {};
};

class TinyPieChart:public TinyChart
{
public:
    void Draw();
    void DrawLegend();
    void DrawFrame();
    void Plot();
    void SetHorziontalScale(STR_VEC& vecXScale);
    void SetVerticalScale(INT_VEC& vecYScale);
    TinyColor GetRandColor(int index=-1);
    TinyPieChart(gdImagePtr im):TinyChart(im), m_nSum(0)
    {

    };
    virtual ~TinyPieChart()
    {};
private:
    int m_nSum;
};
class TinyDiagram
{

public:

    TinyDiagram(const char* filename,int width,int height);
    virtual ~TinyDiagram();

    int SetFileName(const char* szFilename);

    int SetTitle(const char* szTitle);

    virtual void Draw() {};

    void DrawBorder();

    void SetLabels(STR_VEC& xScales);

    void SetValues(INT_VEC& yScales);

    gdImagePtr GetImage()
    {
        return m_pImage;
    };
    void WriteImage();
protected:
    gdImagePtr m_pImage;

    int m_nWidth;
    int m_nHeight;

    char m_szFileName[NAMESIZE];
    char m_szTitle[NAMESIZE];

    INT_VEC m_vecData;
    STR_VEC m_vecName;
};

class TinyTrendlineDiagram:public TinyDiagram
{
public:
    TinyCurveChart* m_pCurveChart;
    TinyColumnChart* m_pColumnChart;

    TinyTrendlineDiagram(const char* filename,int width,int height);
    virtual ~TinyTrendlineDiagram();
    void Draw();
};

class TinyDistributionDiagram:public TinyDiagram
{
public:
    TinyPieChart* m_pPieChart;
    TinyHistogram* m_pHistogram;
    void Draw();
    TinyDistributionDiagram(const char* filename,int width,int height);
    virtual ~TinyDistributionDiagram();

};


#endif /* UTIL_TINYCHART_H_ */

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拘领,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子樱调,更是在濱河造成了極大的恐慌约素,老刑警劉巖届良,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異圣猎,居然都是意外死亡士葫,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進店門送悔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來慢显,“玉大人,你說我怎么就攤上這事欠啤△⒃梗” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵跪妥,是天一觀的道長。 經(jīng)常有香客問我声滥,道長眉撵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任落塑,我火速辦了婚禮纽疟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘憾赁。我一直安慰自己污朽,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布龙考。 她就那樣靜靜地躺著蟆肆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪晦款。 梳的紋絲不亂的頭發(fā)上炎功,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天,我揣著相機與錄音缓溅,去河邊找鬼蛇损。 笑死,一個胖子當(dāng)著我的面吹牛坛怪,可吹牛的內(nèi)容都是我干的淤齐。 我是一名探鬼主播,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼袜匿,長吁一口氣:“原來是場噩夢啊……” “哼更啄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起居灯,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤锈死,失蹤者是張志新(化名)和其女友劉穎贫堰,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體待牵,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡其屏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了缨该。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片偎行。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖贰拿,靈堂內(nèi)的尸體忽然破棺而出蛤袒,到底是詐尸還是另有隱情,我是刑警寧澤膨更,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布妙真,位于F島的核電站,受9級特大地震影響荚守,放射性物質(zhì)發(fā)生泄漏珍德。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一矗漾、第九天 我趴在偏房一處隱蔽的房頂上張望锈候。 院中可真熱鬧,春花似錦敞贡、人聲如沸泵琳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽获列。三九已至,卻和暖如春蛔垢,著一層夾襖步出監(jiān)牢的瞬間蛛倦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工啦桌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留溯壶,地道東北人。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓甫男,卻偏偏與公主長得像且改,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子板驳,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,728評論 2 351

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,872評論 25 707
  • 踏雪雁跡難覓又跛,梅香竹黃已是去年絕調(diào),此去經(jīng)年留別久相思如故若治,暖爐紅袖招慨蓝,掌燈燭上感混,消瓦殘霜且看漁舟獨釣;良月明惹寒...
    不知客閱讀 214評論 0 2
  • 在國內(nèi)不管是那個行業(yè)礼烈,當(dāng)您處在比較領(lǐng)先的地位時弧满,常常會受到一些威脅,以及同行等造謠生事此熬,偽造事實庭呜,以一副同情的姿態(tài)...
    英利浦環(huán)保電器閱讀 846評論 0 0
  • 舅舅和舅媽都是90多歲的老人了募谎,每隔一段時間我總會去看看他們。每一次去他們都非常高興阴汇,盡管行走不是很方便数冬,但...
    長安閑花淡淡春閱讀 451評論 2 1
  • “當(dāng)孩子拒絕穿我選的衣服時,我該怎么辦呢搀庶?”理解你的孩子拐纱、你自己和情形建議:1、盡早讓孩子自己挑選衣服地来。當(dāng)他們穿著...
    小米女_水草萍閱讀 214評論 0 1