語言程序設計-利用Qt5實現(xiàn)學生選課管理系統(tǒng)(超詳細附思路和代碼)

QT安裝

  • QT安裝與基本操作詳細內(nèi)容點這里

任務要求

  • 題目要求如下:

    • 該系統(tǒng)需創(chuàng)建和管理如下信息:
    1. 學生信息:學號匹表、姓名撩银、班級头滔、電話、生日封豪、住址角虫、選課數(shù)據(jù)集末购。
    2. 選課信息:課程編號熙揍、課程名稱、學分盖灸、學期蚁鳖、教室、成績赁炎。
    • 系統(tǒng)功能要求如下:
    1. 創(chuàng)建和管理學生信息的對象醉箕;
    2. 創(chuàng)建和管理選課信息的對象;
    3. 增加和刪除學生徙垫;
    4. 針對特定學生增加和刪除選課信息 讥裤;
    5. 基本查詢功能;
    6. 數(shù)據(jù)文件讀寫:文件中包含所有學生信息姻报、每個學生的選課信息等數(shù)據(jù)己英;
    7. 基本信息顯示:1)所有學生的信息顯示;2)特定學生的選課信息吴旋;
    8. 可選功能提升:特定課程的選課學生顯示损肛、成績排名等厢破。

項目分析

系統(tǒng)設計

分析設計任務可以知道, ==每個學生要包括復數(shù)個課程信息治拿,同時復數(shù)個學生組成學生表== 進行統(tǒng)一管理摩泪。

  • 創(chuàng)建四個類,分別是課程類忍啤、課程表類膝但、學生類撵摆、學生表類妒潭,課程表類中為課程類的列表類侮繁,學生類的成員包括課程表類策治,學生表類為學生類的列表粱年;
  • 因為要針對特定學生或特定課程進行操作矛辕,所以要針對不同的信息顯示界面進行選擇索引的儲存粥航;
  • 作為一個界面程序粟焊,要注意因為一些操作失誤或?qū)Τ绦虿皇煜ざa(chǎn)生的程序崩潰冤狡,盡量避免bug的出現(xiàn)。

功能分析

根據(jù)題目要求项棠,程序要完成以下功能:

  • 添加/刪除學生信息悲雳;
  • 對特定的學生添加/刪除課程信息;
  • 對學生信息/課程信息進行查詢香追,并在查詢后可進行修改或刪除操作合瓢;
  • 數(shù)據(jù)讀寫:可直接讀取/保存到數(shù)據(jù)庫中,也可打開其他文件并另存為透典;
  • 可查找特定課程的選課學生的信息晴楔,并可對成績進行排序;
  • 在操作錯誤時可以彈出對話框提醒峭咒。

設計思路

  • 完成課程類税弃、課程隊列類、學生類凑队、學生隊列類四個類的創(chuàng)建:課程表類中為課程類的列表類则果,學生類的成員包括課程表類,學生表類為學生類的列表漩氨,數(shù)據(jù)結(jié)構如下圖:


  • 界面設計短条,盡量簡潔美觀:
    通過對界面進行不同層次的布局操作讓界面控件大小可以隨窗口大小改變而改變,同時添加對話框中有l(wèi)abel控件提醒才菠,避免空文本的出現(xiàn)茸时;

  • 四個類與界面進行對接,通過界面可對創(chuàng)建類進行操作:
    調(diào)用四個類中的成員函數(shù)赋访,獲取或修改類信息可都,同時用m_View_kind記錄目前視圖類型:==0顯示學生信息缓待,1顯示選課信息,2顯示從0表查詢渠牲,3顯示從1表中查詢,4顯示特定課程的選課學生==旋炒,在不同視圖下可以進行相應的操作,而不能進行的操作签杈,程序會進行提醒瘫镇,避免bug的出現(xiàn);

  • 不同視圖的顯示要及時對視圖種類和選中列表的索引進行刷新:
    ==學生信息視圖作為最底層視圖答姥,在這層視圖時所用選中索引要進行刷新铣除,學生信息視圖作為主視圖,課程信息視圖作為副主視圖鹦付,索引的刷新在這兩個視圖中進行==尚粘,結(jié)構如下圖;

  • 在查詢時要將查詢結(jié)果的索引及時儲存
    方便直接對查詢結(jié)果進行操作敲长,并注意推出查詢要及時刷新郎嫁,==其中學生信息查詢結(jié)果中的索引放入indexlist中,課程信息查詢結(jié)果中的索引放入indexlist1中==祈噪,可直接在查詢結(jié)果視圖中對成員對象進行操作泽铛;

  • 特定課程進行學生信息顯示:
    通過對所有學生進行遍歷操作進行查找,將結(jié)果索引進行儲存顯示辑鲤,成績排序運用QList中的qSort()函數(shù)直接對結(jié)構體中的某個屬性進行排序厚宰;

  • 在操作失誤時會有提醒對話框:
    創(chuàng)建一個提醒對話框,在進行可能會導致程序崩潰的操作時彈出制止遂填;

文件與對象描述(代碼)

課程類

文件:course.h\ .cpp//課程類:
c_ID//課程編號铲觉;c_Name//課程名稱;credit//學分吓坚;term//學期撵幽;c_room//教室;grade//成績

  • course.h
#include<QTextStream>
#include<qstring.h>
#include<qdatetime.h>
#include<qlist.h>
#include<QFile>
#include <QMessageBox>
#include<QFileDialog>
#include<QTextCodec>
#include <QAbstractItemDelegate>
#include<QAbstractItemView>

class Course
{
public:
    Course();
    virtual ~Course();
    Course& operator= (const Course & course);

    void SaveCourse(QTextStream &aStream); //往流文件中寫入成績
    void ReadCourse(QTextStream &aStream); //從流文件中讀成績

    QString c_ID;      //課程編號
    QString c_Name;    //課程名稱
    float credit;      //學分
    QString term;      //學期
    QString c_room;    //教室
    float grade;       //成績
};
  • course.cpp
#include "course.h"

Course::Course()
{
    c_ID="";
    c_Name="";
    credit=0;
    term="";
    c_room="";
    grade=0;
}

Course::~Course()
{

}

Course& Course::operator=(const Course &course)
{
    c_ID=course.c_ID;
    c_Name=course.c_Name;
    credit=course.credit;
    term=course.term;
    c_room=course.c_room;
    grade=course.grade;

    return *this;
}

void Course::SaveCourse(QTextStream &aStream)
{
    aStream<<c_ID<<"\t"<<c_Name<<"\t"<<credit<<"\t"<<term<<"\t"<<c_room<<"\t"<<grade<<"\n";
}

void Course::ReadCourse(QTextStream &aStream)
{
    aStream>>c_ID;
    aStream>>c_Name;
    aStream>>credit;
    aStream>>term;
    aStream>>c_room;
    aStream>>grade;
}

課程表類

這里課程表和后面的學生表用==QT5中的Qlist< Data >數(shù)據(jù)類型==礁击;
文件:courseinfotable.h\ .cpp//課程隊列類:
m_course//課程類列表Qlist<Course>盐杂;c_num//課程數(shù)

  • courseinfotable.h
#include"course.h"

class CourseInfoTable
{
public:
    CourseInfoTable();
    CourseInfoTable& operator= (const CourseInfoTable & course);

    void SaveCourseInfoTable(QTextStream &aStream); //往流文件中寫入成績
    void ReadCourseInfoTable(QTextStream &aStream);

    void AddCourse(Course& course);           //添加課程到課程表中
    void DelCourse(int index);                //根據(jù)列表索引刪除課程
    Course& GetCourse(int index);             //根據(jù)列表索引得到課程
    int CourseNum();                          //得到課表課程數(shù)量

    QList<Course> m_course;                   //課程列表
    int c_num;                                //課程數(shù)量

};
  • courseinfotable.cpp
#include "courseinfotable.h"

CourseInfoTable::CourseInfoTable()
{
    m_course={};
    c_num=0;
}

CourseInfoTable& CourseInfoTable::operator=(const CourseInfoTable &course)
{
    m_course=course.m_course;
    c_num=course.c_num;
    return *this;
}

int CourseInfoTable::CourseNum()
{
    c_num=m_course.size();
    return this->c_num;
}

void CourseInfoTable::SaveCourseInfoTable(QTextStream &aStream)
{
    int num=CourseNum();
    aStream<<num<<"\n";
    for(int i=0;i<num;i++)
    {
       Course temp = m_course[i];
       temp.SaveCourse(aStream);
    }
}


void CourseInfoTable::ReadCourseInfoTable(QTextStream &aStream)
{
    aStream>>c_num;
    for(int i=0;i<c_num;i++)
    {
        Course temp;
        temp.ReadCourse(aStream);
        m_course.append(temp);
    }
}


void CourseInfoTable::AddCourse(Course &course)
{
    m_course.append(course);
}

void CourseInfoTable::DelCourse(int index)
{
    m_course.removeAt(index);
    c_num-=1;
}

Course& CourseInfoTable::GetCourse(int index)
{
    return m_course[index];
}

學生類

文件:student.h\ .cpp//學生類:
s_ID//學號;s_Name//姓名哆窿;s_class//班級链烈;ph_number//電話;birthday//生日挚躯;adress//地址强衡;s_courses//課程隊列類CourseInfoTable

  • student.h
class Student
{
public:
    Student();
    Student& operator= (const Student& man);
    virtual ~Student();

    void SaveStudent(QTextStream &aStream);     //保存數(shù)據(jù)
    void ReadStudent(QTextStream &aStream);     //讀取數(shù)據(jù)

    bool is_courses();     //判斷是否選課

    QString s_ID;          //學號
    QString s_Name;        //姓名
    QString s_class;       //班級
    QString ph_number;     //電話
    QDate birthday;        //生日
    QString adress;       //地址
    CourseInfoTable s_courses; //課程隊列類
};
  • student.cpp
#include "student.h"

Student::Student()
{
    s_ID="";
    s_Name="";
    s_class="";
    ph_number="";
    birthday=QDate();
    adress="";
    s_courses=CourseInfoTable();
}

Student::~Student()
{

}

Student& Student::operator=(const Student &man)
{
    s_ID=man.s_ID;
    s_Name=man.s_Name;
    s_class=man.s_class;
    ph_number=man.ph_number;
    birthday=man.birthday;
    adress=man.adress;
    s_courses=man.s_courses;
    return *this;
}

void Student::SaveStudent(QTextStream &aStream)
{
    aStream<<s_ID<<"\t";
    aStream<<s_Name<<"\t";
    aStream<<s_class<<"\n";
    aStream<<ph_number<<"\n";
    aStream<<birthday.year()<<"\t"<<birthday.month()<<"\t"<<birthday.day()<<"\n";
    aStream<<adress<<"\n";
    s_courses.CourseInfoTable::SaveCourseInfoTable(aStream);
}

void Student::ReadStudent(QTextStream &aStream)
{
    int year,month,day;
    aStream>>s_ID;
    aStream>>s_Name;
    aStream>>s_class;
    aStream>>ph_number;
    aStream>>year;
    aStream>>month;
    aStream>>day;
    aStream>>adress;
    birthday.setDate(year,month,day);
    s_courses.ReadCourseInfoTable(aStream);
}

bool Student::is_courses()
{
    return s_courses.CourseNum()==0;
}

學生表類

文件:studentinfotable.h.cpp//學生隊列類:
m_student//學生隊列類QList<Student>;s_num//學生數(shù)量

  • studentinfotable.h
class StudentInfoTable
{
public:
    StudentInfoTable();
    StudentInfoTable& operator= (const StudentInfoTable & student);

    void SaveStudentInfoTable(QTextStream &aStream); //往流文件中寫入數(shù)據(jù)
    void ReadCourseInfoTable(QTextStream &aStream); //從流文件中讀取數(shù)據(jù)

    void AddStudent(Student& student);           //添加學生添加到學生表中
    void DelStudent(int index);                //根據(jù)列表索引刪除學生
    Student& GetStudent(int index);             //根據(jù)列表索引得到學生
    int StudentNum();                          //得到學生數(shù)量

    QList<Student> m_student;  //學生表
    int s_num;   //學生數(shù)量
};
  • studentinfotable.cpp
#include "studentinfotable.h"

StudentInfoTable::StudentInfoTable()
{
   m_student=QList<Student>();
   s_num=0;
}

StudentInfoTable& StudentInfoTable::operator=(const StudentInfoTable &student)
{
    m_student=student.m_student;
    s_num=student.s_num;
    return *this;
}

void StudentInfoTable::SaveStudentInfoTable(QTextStream &aStream)
{
    int num=StudentNum();
    aStream<<num<<"\n";
    for(int i=0;i<num;i++)
    {
        m_student[i].SaveStudent(aStream);
        aStream<<"\n";
    }
}

void StudentInfoTable::ReadCourseInfoTable(QTextStream &aStream)
{
    aStream>>s_num;

    for(int i=0;i<s_num;i++)
    {
        Student temp_s;
        temp_s.ReadStudent(aStream);
        m_student.append(temp_s);
    }
}

void StudentInfoTable::AddStudent(Student &student)
{
    m_student.append(student);
    s_num+=1;
}

void StudentInfoTable::DelStudent(int index)
{
    m_student.removeAt(index);
    s_num-=1;
}

Student& StudentInfoTable::GetStudent(int index)
{
    return m_student[index];
}

int StudentInfoTable::StudentNum()
{
    s_num=m_student.size();
    return s_num;
}

UI設計

創(chuàng)建方法:

  • 右擊項目>>Add new>>Qt>>Qt設計師界面類


  • 可以選擇各種不同類別的對話框和主界面


  • 創(chuàng)建成功后會自動生成.h .cpp和.ui文件码荔,雙擊.ui文件即可對界面進行設計布局漩勤。

添加學生信息對話框

文件:inputdialog_s.h\ .cpp\ .ui//添加學生對話框類:
返回對話框中textEdit中的文本

  • inputdialog_s.ui界面設計

    ==注意==:
    • 在界面設計完后要對項目進行構建(點那個小錘子)感挥,這樣在編輯.h和.cpp文件時在才會有我們添加的控件對象。
    • 選擇任意一個控件右鍵會有轉(zhuǎn)到槽的選項越败,比如在這個對話框中選擇textEdit控件:
  • 比如我們選擇textChange()函數(shù)触幼,它就會出現(xiàn)在.h文件中,它表示當textEdit控件中文本發(fā)生變化時究飞,該函數(shù)就會運行置谦,其他槽函數(shù)可以自行查找官方文檔

  • inputdialog_s.h(在創(chuàng)建后有一部分已經(jīng)存在了亿傅,這里就直接貼過來啦

#include <QDialog>
#include<QTextEdit>

namespace Ui {
class InputDialog_s;
}

class InputDialog_s : public QDialog
{
    Q_OBJECT

public:
    explicit InputDialog_s(QWidget *parent = nullptr);
    ~InputDialog_s();
    
    QString is_Error(); //
    void Show_error(const QString&tempstr);
    //得到文本編輯框中的文本內(nèi)容媒峡,方便后面與主窗口對接
    QString Get_ID();
    QString Get_Name();
    QString Get_Class();
    QString Get_number();
    QDate Get_bir();
    QString Get_adress();
    
    void Label_Show();

private slots:
    void on_textEdit_selectionChanged();

    void on_textEdit_6_selectionChanged();

    void on_textEdit_2_selectionChanged();

    void on_textEdit_3_selectionChanged();

    void on_textEdit_4_selectionChanged();

    void on_dateEdit_editingFinished();

    void on_textEdit_textChanged();

    void on_textEdit_2_textChanged();

    void on_textEdit_3_textChanged();

    void on_textEdit_4_textChanged();

    void on_textEdit_6_textChanged();

private:
    Ui::InputDialog_s *ui;
};

  • inputdialog_s.cpp
#include "inputdialog_s.h"
#include "ui_inputdialog_s.h"

InputDialog_s::InputDialog_s(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::InputDialog_s)
{
    ui->setupUi(this);
}

InputDialog_s::~InputDialog_s()
{
    delete ui;
}

QString InputDialog_s::Get_ID()
{
    return ui->textEdit->toPlainText();
}

QString InputDialog_s::Get_Name()
{
    return ui->textEdit_2->toPlainText();
}

QString InputDialog_s::Get_Class()
{
    return ui->textEdit_3->toPlainText();
}

QString InputDialog_s::Get_number()
{
    return ui->textEdit_4->toPlainText();
}

QDate InputDialog_s::Get_bir()
{
    return ui->dateEdit->date();
}

QString InputDialog_s::Get_adress()
{
    return ui->textEdit_6->toPlainText();
}

QString InputDialog_s::is_Error()
{
    QString error;
    if(Get_ID().isEmpty())
    {
        error="學號";
        return error;
    }
    else if(Get_Name().isEmpty())
    {
        error="姓名";
        return error;
    }
    else if(Get_Class().isEmpty())
    {
        error="班級";
        return error;
    }
    else if(Get_number().isEmpty())
    {
        error="電話";
        return error;
    }
    else if(Get_adress().isEmpty())
    {
        error="地址";
        return error;
    }
    else
    {
        error="OK";
        return error;
    }
}

void InputDialog_s::Show_error(const QString &tempstr)
{
    ui->label_7->setText(tempstr);
    ui->label_7->setAlignment(Qt::AlignRight);
}

void InputDialog_s::Label_Show()
{
    QString error=is_Error();
    if(error=="OK")Show_error("點擊OK即可添加!");
    else Show_error(QString("%1為空袱蜡!請輸入K坎洹慢宗!").arg(error));
}

void InputDialog_s::on_textEdit_selectionChanged()
{
    Label_Show();
}

void InputDialog_s::on_textEdit_6_selectionChanged()
{
    Label_Show();
}

void InputDialog_s::on_textEdit_2_selectionChanged()
{
    Label_Show();
}

void InputDialog_s::on_textEdit_3_selectionChanged()
{
    Label_Show();
}

void InputDialog_s::on_textEdit_4_selectionChanged()
{
    Label_Show();
}

void InputDialog_s::on_dateEdit_editingFinished()
{
    Label_Show();
}

void InputDialog_s::on_textEdit_textChanged()
{
    Label_Show();
}

void InputDialog_s::on_textEdit_2_textChanged()
{
    Label_Show();
}

void InputDialog_s::on_textEdit_3_textChanged()
{
    Label_Show();
}

void InputDialog_s::on_textEdit_4_textChanged()
{
    Label_Show();
}

void InputDialog_s::on_textEdit_6_textChanged()
{
    Label_Show();
}
  • 運行效果如下:


添加選課信息對話框

  • 與添加學生信息相似

  • 文件:inputdialog_c.h\ .cpp\ .ui//添加課程對話框類:
    返回對話框中textEdit中的文本

  • inputdialog_c.ui界面設計


  • inputdialog_c.h

#include <QDialog>

namespace Ui {
class InputDialog_c;
}

class InputDialog_c : public QDialog
{
    Q_OBJECT

public:
    explicit InputDialog_c(QWidget *parent = nullptr);
    ~InputDialog_c();

    QString is_Error();      //錯誤類型
    void Show_error(const QString&tempstr);  //判斷編輯框中內(nèi)容是否為空
    
     //得到文本編輯框中的文本內(nèi)容坪蚁,方便后面與主窗口對接
    void Show_Label();
    QString Get_ID();
    QString Get_Name();
    float Get_Credit();
    QString Get_term();
    QString Get_room();
    float Get_grade();

private slots:
    void on_textEdit_selectionChanged();

    void on_textEdit_textChanged();

    void on_textEdit_2_selectionChanged();

    void on_textEdit_2_textChanged();

    void on_textEdit_3_selectionChanged();

    void on_textEdit_3_textChanged();

    void on_textEdit_4_selectionChanged();

    void on_textEdit_4_textChanged();

    void on_textEdit_5_selectionChanged();

    void on_textEdit_5_textChanged();

    void on_textEdit_6_textChanged();

    void on_textEdit_6_selectionChanged();

private:
    Ui::InputDialog_c *ui;
};
  • inputdialog_c.cpp
#include "inputdialog_c.h"
#include "ui_inputdialog_c.h"

InputDialog_c::InputDialog_c(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::InputDialog_c)
{
    ui->setupUi(this);
}

InputDialog_c::~InputDialog_c()
{
    delete ui;
}

QString InputDialog_c::Get_ID()
{
    return ui->textEdit->toPlainText();
}

QString InputDialog_c::Get_Name()
{
    return ui->textEdit_2->toPlainText();
}

float InputDialog_c::Get_Credit()
{
    return ui->textEdit_3->toPlainText().toFloat();
}

QString InputDialog_c::Get_term()
{
    return ui->textEdit_4->toPlainText();
}

QString InputDialog_c::Get_room()
{
    return ui->textEdit_5->toPlainText();
}

float InputDialog_c::Get_grade()
{
    return ui->textEdit_6->toPlainText().toFloat();
}

QString InputDialog_c::is_Error()
{
    QString error;
    if(Get_ID().isEmpty())
    {
        error="課程編號";
        return error;
    }
    else if(Get_Name().isEmpty())
    {
        error="課程名稱";
        return error;
    }
    else if(ui->textEdit_3->toPlainText().isEmpty())
    {
        error="學分";
        return error;
    }
    else if(Get_term().isEmpty())
    {
        error="學期";
        return error;
    }
    else if(Get_room().isEmpty())
    {
        error="教室";
        return error;
    }
    else if(ui->textEdit_6->toPlainText().isEmpty())
    {
        error="成績";
        return error;
    }
    else
    {
        error="OK";
        return error;
    }
}

void InputDialog_c::Show_error(const QString &tempstr)
{
    ui->label_7->setText(tempstr);
    ui->label_7->setAlignment(Qt::AlignRight);
}

void InputDialog_c::Show_Label()
{
    QString error=is_Error();
    if(error=="OK")Show_error("點擊OK即可添加!");
    else Show_error(QString("%1為空镜沽!請輸入C粑睢!").arg(error));
}

void InputDialog_c::on_textEdit_selectionChanged()
{
    Show_Label();
}


void InputDialog_c::on_textEdit_textChanged()
{
    Show_Label();
}

void InputDialog_c::on_textEdit_2_selectionChanged()
{
    Show_Label();
}

void InputDialog_c::on_textEdit_2_textChanged()
{
    Show_Label();
}

void InputDialog_c::on_textEdit_3_selectionChanged()
{
    Show_Label();
}

void InputDialog_c::on_textEdit_3_textChanged()
{
    Show_Label();
}

void InputDialog_c::on_textEdit_4_selectionChanged()
{
    Show_Label();
}

void InputDialog_c::on_textEdit_4_textChanged()
{
    Show_Label();
}

void InputDialog_c::on_textEdit_5_selectionChanged()
{
    Show_Label();
}

void InputDialog_c::on_textEdit_5_textChanged()
{
    Show_Label();
}

void InputDialog_c::on_textEdit_6_textChanged()
{
    Show_Label();
}

void InputDialog_c::on_textEdit_6_selectionChanged()
{
    Show_Label();
}

  • 運行效果如下:


信息查詢對話框

==注意==:這里的查詢對話框只是得到查詢信息的關鍵詞缅茉,真正的查詢的運行是在主窗口(MainWindow)中嘴脾。

學生信息查詢

文件:selectdialog.h\ .cpp\ .ui//學生查詢對話框:
可通過學號、姓名蔬墩、班級三個特征進行查詢

  • selectdialog.ui設計


  • selectdialog.h
#include <QDialog>

namespace Ui {
class SelectDialog;
}

class SelectDialog : public QDialog
{
    Q_OBJECT

public:
    explicit SelectDialog(QWidget *parent = nullptr);
    ~SelectDialog();

    QString Get_Value();//得到特征字符串
    int Get_Comboboxindex();//得到特征索引
    QString Get_Comboboxtext();//得到特征文本

private slots:
    void on_comboBox_currentIndexChanged(const QString &arg1);

private:
    Ui::SelectDialog *ui;
    int m_index;             //組合框索引
};

  • selectdialog.cpp
#include "selectdialog.h"
#include "ui_selectdialog.h"

SelectDialog::SelectDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::SelectDialog)
{
    ui->setupUi(this);

    m_index=0;
}

SelectDialog::~SelectDialog()
{
    delete ui;
}

QString SelectDialog::Get_Value()
{
    return ui->textEdit->toPlainText();
}

int SelectDialog::Get_Comboboxindex()
{
    return m_index;
}

void SelectDialog::on_comboBox_currentIndexChanged(const QString &arg1)
{
    if(arg1=="學號")
        m_index=0;
    else if(arg1=="姓名")
        m_index=1;
    else m_index=2;
}

QString SelectDialog::Get_Comboboxtext()
{
    if(m_index==0)return QString("學號");
    else if(m_index==1)return QString("姓名");
    else return QString("班級");
}

選課信息查詢

==與學生信息查詢相似==

文件:selectdialog1.h\ .cpp\ .ui//課程查詢對話框:
可通過課程編號译打、課程名稱兩個特征進行查詢

  • selectdialog1.ui設計


  • selectdialog1.h
#include <QDialog>

namespace Ui {
class SelectDialog1;
}

class SelectDialog1 : public QDialog
{
    Q_OBJECT

public:
    explicit SelectDialog1(QWidget *parent = nullptr);
    ~SelectDialog1();

    QString Get_Value();//得到特征字符串
    int Get_Comboboxindex();//得到特征索引
    QString Get_Comboboxtext();//得到特征文本

private slots:
    void on_comboBox_currentIndexChanged(const QString &arg1);

private:
    Ui::SelectDialog1 *ui;
    int m_index;         //組合框索引
};
  • selectdialog1.cpp
#include "selectdialog1.h"
#include "ui_selectdialog1.h"

SelectDialog1::SelectDialog1(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::SelectDialog1)
{
    ui->setupUi(this);

    m_index=0;
}

SelectDialog1::~SelectDialog1()
{
    delete ui;
}

QString SelectDialog1::Get_Value()
{
    return ui->textEdit->toPlainText();
}

int SelectDialog1::Get_Comboboxindex()
{
    return m_index;
}

QString SelectDialog1::Get_Comboboxtext()
{
    if(m_index==0)return QString("課程編號");
    else return QString("課程名稱");
}

void SelectDialog1::on_comboBox_currentIndexChanged(const QString &arg1)
{
    if(arg1=="課程編號")
        m_index=0;
    else m_index=1;
}

提示對話框

文件:tipsdialog.h\ .cpp\ .ui//提醒對話框:
避免一些禁止操作,并提醒

  • tipsdialog.ui


  • tipsdialog.h

#include <QDialog>

namespace Ui {
class TipsDialog;
}

class TipsDialog : public QDialog
{
    Q_OBJECT

public:
    explicit TipsDialog(QWidget *parent = nullptr);
    ~TipsDialog();
    void Tips_Show(const QString&tempstr);

private:
    Ui::TipsDialog *ui;
};
  • tipsdialog.cpp
#include "tipsdialog.h"
#include "ui_tipsdialog.h"

TipsDialog::TipsDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::TipsDialog)
{
    ui->setupUi(this);
    setWindowTitle("提示");
}

TipsDialog::~TipsDialog()
{
    delete ui;
}

void TipsDialog::Tips_Show(const QString &tempstr)
{
    ui->label->setText(tempstr);
}

主窗口設計?

概覽

文件:mainwindow.h\ .cpp\ .ui//主窗口:
*ui//主窗口對象拇颅; *studentTableView//表格視圖對象奏司; m_students//學生隊列類; m_View_kind//目前視圖類型0顯示學生信息樟插,1顯示選課信息韵洋,2顯示從0表查詢,3顯示從1表中查詢,4顯示特定課程的選課學生黄锤; m_row//學生視圖0選中索引搪缨; indexlist//記錄學生信息0中查詢結(jié)果索引,在查詢視圖可以進行刪除鸵熟、修改操作QList<int>; m_row1//課程信息視圖1選中索引副编; indexlist1//記錄課程信息1中查詢結(jié)果索引,在查詢視圖可以進行刪除流强、修改操作QList<int>;

  • 頭文件代碼如下:
#include <QMainWindow>
#include<QStandardItemModel>
#include"studentinfotable.h"
#include <QAbstractItemDelegate>
#include <QModelIndex>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void Show_Label1(const QString&tempstr);//數(shù)量顯示
    void Show_Label2(const QString&tempstr);//進程提醒
    void Show_Label(const QString&tempstr);//名單備注

    void Show_StudentTable();         //顯示學生信息(不可修改)0
    void Show_Table_s_changed();      //顯示可修改

    void Show_CourseTable();          //顯示選課信息(不可修改)1
    void Show_Table_c_changed();      //顯示可修改

    void Show_SelectTable();          //顯示查詢結(jié)果(不可修改)2->0;3->1
    void Show_Table_sc_changed();     //顯示可修改

    void Show_CtoSTable();            //顯示特定課程的學生信息(不可修改)4

private slots:
    void on_actionOpen_triggered();   //打開文件

    void on_actionSave_triggered();   //保存數(shù)據(jù)

    void on_actionLoading_triggered(); //讀取數(shù)據(jù)

    void on_actionSaveto_triggered();  //另存為

    void on_actionAdd_s_triggered();   //添加學生

    void on_actionShow_s_triggered();  //學生信息視圖

    void on_tableView_clicked(const QModelIndex &index);  //獲取鼠標選中表格的索引

    void on_actionDel_s_triggered();    //刪除特定學生

    void on_actionAdd_c_triggered();    //為特定學生添加課程信息

    void on_actionShow_c_triggered();   //課程信息顯示

    void on_actionDel_c_triggered();    //刪除某個課程信息

    void on_actionSelect_triggered();   //查詢

    void on_ShowInfotableView_changed();     //修改數(shù)據(jù)

    void on_actionChange_triggered();       //修改

    void on_actionChangedSave_triggered();   //保存修改(推出修改)


    void on_actionCtoS_Show_triggered();     //顯示特定課程的學生信息

    void on_actionAscending_triggered();     //升序

    void on_actionDescending_triggered();    //降序

    void on_tableView_doubleClicked(const QModelIndex &index);

private:
    Ui::MainWindow *ui;                   //界面
    QStandardItemModel *studentTableView; //表格視圖
    StudentInfoTable m_students;          //學生名單類

    int m_View_kind;                      //目前表格顯示狀態(tài),0顯示學生信息齿桃,1顯示選課信息惑惶,
                                          //2顯示從0表查詢,3顯示從1表中查詢,4顯示特定課程的選課學生

    int m_row;                            //0表中選中的行數(shù)
    QList<int> indexlist;                 //記錄0中查詢結(jié)果索引短纵,在查詢視圖可以進行刪除带污、修改操作

    int m_row1;                           //1表中選中的行數(shù)
    QList<int> indexlist1;                //記錄1中查詢結(jié)果索引,在查詢視圖可以進行刪除香到、修改操作

    bool can_change;                      //是否進行修改

};

界面UI設計

直接利用添加菜單欄功能鱼冀,大體設計如下:


==注意==:在添加完菜單功能時,會自動生成該Action Editor悠就,如下圖:

==右鍵選擇轉(zhuǎn)到槽后會在mainwindow.h中自動生成該對應的槽函數(shù)==千绪,如下圖:


==因為該cpp文件不少于1000行,這里就詳細解釋幾個重要的操作梗脾,其他的可以舉一反三==荸型。

構造函數(shù)

#include"readonlydelegate.h"
#include"tipsdialog.h"
#include"inputdialog_c.h"
#include"selectdialog.h"
#include"selectdialog1.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    //建立view模型
    ui->tableView->setSelectionMode(QAbstractItemView::SingleSelection);//單次選擇
    ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);//選中一個item

    studentTableView=new QStandardItemModel();
    //關聯(lián)
    ui->tableView->setModel(studentTableView);
    //信號與槽進行連接(后續(xù)可在tabelView中直接修改)
    connect(ui->tableView->itemDelegate(),&QAbstractItemDelegate::closeEditor,this,&MainWindow::on_ShowInfotableView_changed);
    //成員默認構造
    m_View_kind=0;
    m_row=-1;
    indexlist=QList<int>();
    m_row1=-1;
    indexlist1=QList<int>();
    can_change=false;
}

打開保存文件

  • 學生表類中我們已經(jīng)寫好了文件讀取和文件保存,這里直接調(diào)用就好
//打開一個文件
void MainWindow::on_actionOpen_triggered()
{
    QString curPath = QDir::currentPath();
    QString dlgTitle = "選擇一個文件";
    QString filter = "文本文件(*.txt);;所有文件(*.*)";
    QString aFileName = QFileDialog::getOpenFileName(this, dlgTitle, curPath, filter);

    if(aFileName.isEmpty())
    {

        Show_Label2("打開文件失斦搿瑞妇!");
        return;
    }

    Show_Label2("正在打開文件。梭冠。辕狰。");
    //創(chuàng)建成功,打開文件
    QFile aFile(aFileName);

    if(!aFile.exists()) //文件不存在
    {

        Show_Label2("打開文件失斂啬蔓倍!");
        return;
    }
    if(!aFile.open(QIODevice::ReadOnly | QIODevice::Text)) //以文本方式打開
    {
        Show_Label2("打開文件失敗盐捷!");
        return;
    }

    m_students=StudentInfoTable();//清空

    QTextStream aStream(&aFile); //用文本流讀取文件
    aStream.setCodec(QTextCodec::codecForName("system")); //顯示漢字

    m_students.ReadCourseInfoTable(aStream);
    aFile.close();//關閉文件
    Show_Label2("文件讀取成功偶翅!");

    Show_StudentTable();
}

//保存一個文件
void MainWindow::on_actionSaveto_triggered()
{
    QString curPath = QDir::currentPath();
    QString dlgTitle = "另存為一個文件";
    QString filter = "文本文件(*.txt);;所有文件(*.*)";
    QString aFileName = QFileDialog::getSaveFileName(this, dlgTitle, curPath, filter);
    if(aFileName.isEmpty())
    {

        Show_Label2("保存文件失敗碉渡!");
        return;
    }


    QFile aFile(aFileName);
    if(!aFile.open(QIODevice::WriteOnly| QIODevice::Text)) //保存為文本
    {

        Show_Label2("保存文件失斁鬯!");
        return;
    }

    QTextStream aStream(&aFile);//用文本流保存文件
    aStream.setCodec(QTextCodec::codecForName("system")); //顯示漢字

    m_students.SaveStudentInfoTable(aStream);
    aFile.close();//關閉文件
    Show_Label2("文件保存成功爆价!");
}

表格視圖控件(tableView)使用?

  • 上面貼的頭文件和構造函數(shù)里我們已經(jīng)構造了表格視圖對象
    QStandardItemModel *studentTableView; //表格視圖
  • 下面我將介紹以下如何填充這個表格(以學生信息為例)垦巴,代碼如下:
void MainWindow::Show_StudentTable()
{
    //不能修改
    ui->tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    can_change=false;

    //顯示學生信息
    m_View_kind=0;
    //重置選擇行
    m_row=-1;
    m_row1=-1;
    Show_Label("學生信息視圖");

    studentTableView->clear();
    studentTableView->setColumnCount(7); //7列

    //表頭
    //學號、姓名铭段、班級骤宣、電話、生日序愚、地址憔披、是否選課
    QStringList templist;
    templist<<"學號"<<"姓名"<<"班級"<<"電話"<<"生日"<<"地址"<<"是否選課";
    studentTableView->setHorizontalHeaderLabels(templist);

    int RowCnt=m_students.StudentNum();//行數(shù)(不含標題)
    studentTableView->setRowCount(RowCnt);

    //遍歷插入數(shù)據(jù)
    QStandardItem *aTempItem;//臨時的item
    QString tempstr;
    for(int i=0;i<RowCnt;++i)
    {
        Student temp_s=m_students.GetStudent(i);

        tempstr=temp_s.s_ID;
        aTempItem=new QStandardItem(tempstr);
        studentTableView->setItem(i,0,aTempItem);

        tempstr=temp_s.s_Name;
        aTempItem=new QStandardItem(tempstr);
        studentTableView->setItem(i,1,aTempItem);

        tempstr=temp_s.s_class;
        aTempItem=new QStandardItem(tempstr);
        studentTableView->setItem(i,2,aTempItem);

        tempstr=temp_s.ph_number;
        aTempItem=new QStandardItem(tempstr);
        studentTableView->setItem(i,3,aTempItem);

        tempstr=temp_s.birthday.toString("yyyy/MM/dd");
        aTempItem=new QStandardItem(tempstr);
        studentTableView->setItem(i,4,aTempItem);

        tempstr=temp_s.adress;
        aTempItem=new QStandardItem(tempstr);
        studentTableView->setItem(i,5,aTempItem);

        if(temp_s.is_courses())tempstr="否";
        else tempstr="是";
        aTempItem=new QStandardItem(tempstr);
        studentTableView->setItem(i,6,aTempItem);
    }
    Show_Label1(QString("學生人數(shù):%1人").arg(m_students.StudentNum()));

    //設置內(nèi)容為只讀
    //ReadOnlyDelegate* readOnlyDelegate = new ReadOnlyDelegate(this);
    //ui->tableView->setItemDelegateForColumn(6, readOnlyDelegate);

}
  • 不管是選課信息的顯示還是查詢信息的顯示都與上面的相似

得到鼠標選中的信息索引

  • 因為我們要對==特定的學生或者特定的課程==進行相關操作,所以我們在不同視圖下要得到我們鼠標選中的索引芬膝,代碼如下:
//為tableView控件的槽函數(shù)望门,函數(shù)參數(shù)為鼠標選中的表格索引
void MainWindow::on_tableView_clicked(const QModelIndex &index)
{
    if(m_View_kind==0)
    {
        m_row=index.row();
        Show_Label2(QString("已選中學號為%1 姓名為%2的學生").arg(m_students.GetStudent(m_row).s_ID).arg(m_students.GetStudent(m_row).s_Name));
    }
    else if(m_View_kind==1)
    {
        m_row1=index.row();
        Show_Label2(QString("已選中課程編號為%1 名稱為%2的課程信息").arg(m_students.GetStudent(m_row).s_courses.GetCourse(m_row1).c_ID).arg(m_students.GetStudent(m_row).s_courses.GetCourse(m_row1).c_Name));
    }
    else if(m_View_kind==2)
    {
        if(indexlist.isEmpty())m_row=-1;
        else
        {
            m_row=indexlist[index.row()];
            Show_Label2(QString("已選中學號為%1 姓名為%2的學生").arg(m_students.GetStudent(m_row).s_ID).arg(m_students.GetStudent(m_row).s_Name));
        }
    }
    else if(m_View_kind==3)
    {
        if(indexlist1.isEmpty())m_row1=-1;
        else
        {
            m_row1=indexlist1[index.row()];
            Show_Label2(QString("已選中課程編號為%1 名稱為%2的課程信息").arg(m_students.GetStudent(m_row).s_courses.GetCourse(m_row1).c_ID).arg(m_students.GetStudent(m_row).s_courses.GetCourse(m_row1).c_Name));
        }
    }
}
  • 既然得到了特定索引就可以實現(xiàn)對特定學生或?qū)μ囟ㄕn程的操作,這里就不再贅述和貼代碼啦锰霜。

信息查詢

  • 對接查詢對話框筹误,遍歷查找,代碼如下:
void MainWindow::on_actionSelect_triggered()
{
    Show_Label2("正在進行查詢癣缅。厨剪。。");

    //查詢前清空索引列表
    indexlist.clear();
    indexlist1.clear();

    //在學生信息視圖下
    if(m_View_kind==0 || m_View_kind==2)
    {
        SelectDialog sg1;
        sg1.setWindowTitle("學生信息查詢");
        int ret=sg1.exec();

        if(ret==QDialog::Accepted)
        {
            int index=sg1.Get_Comboboxindex();//查詢特征索引0為學號友存,1為姓名祷膳,2為班級
            QString tempstr=sg1.Get_Value(); //查詢特征值

            //遍歷數(shù)據(jù)
            for(int i=0;i<m_students.StudentNum();i++)
            {
                if(index==0)
                {
                    if(m_students.GetStudent(i).s_ID==tempstr)
                        indexlist.append(i);     //記錄列表中
                }

                if(index==1)
                {
                    if(m_students.GetStudent(i).s_Name==tempstr)
                        indexlist.append(i);     //記錄列表中
                }

                if(index==2)
                {
                    if(m_students.GetStudent(i).s_class==tempstr)
                        indexlist.append(i);     //記錄列表中
                }
            }

            //判斷列表是否為空
            if(indexlist.isEmpty())
                Show_Label2(QString("未找到%1為%2的學生信息").arg(sg1.Get_Comboboxtext()).arg(tempstr));
            else Show_Label2(QString("成功找到%1為%2的學生信息!").arg(sg1.Get_Comboboxtext()).arg(tempstr));

            Show_SelectTable();
        }

        else Show_Label2("查詢操作已取消屡立!");

    }
    //在選課信息視圖下
    else if(m_View_kind==1 || m_View_kind==3)
    {
        SelectDialog1 sg1;
        sg1.setWindowTitle("課程信息查詢");
        int ret=sg1.exec();

        if(ret==QDialog::Accepted)
        {
            int index=sg1.Get_Comboboxindex();//查詢特征索引0為課程編號直晨,1為課程名稱
            QString tempstr=sg1.Get_Value(); //查詢特征值

            //遍歷數(shù)據(jù)
            for(int i=0;i<m_students.GetStudent(m_row).s_courses.CourseNum();i++)
            {
                Course temp_c=m_students.GetStudent(m_row).s_courses.GetCourse(i);
                if(index==0)
                {
                    if(temp_c.c_ID==tempstr)
                        indexlist1.append(i);     //記錄列表中
                }

                if(index==1)
                {
                    if(temp_c.c_Name==tempstr)
                        indexlist1.append(i);     //記錄列表中
                }

            }

            //判斷列表是否為空
            if(indexlist1.isEmpty())
                Show_Label2(QString("未找到%1為%2的課程信息").arg(sg1.Get_Comboboxtext()).arg(tempstr));
            else Show_Label2(QString("成功找到%1為%2的課程信息!").arg(sg1.Get_Comboboxtext()).arg(tempstr));

            Show_SelectTable();
        }

        else Show_Label2("查詢操作已取消膨俐!");

    }
    else
    {
        TipsDialog tig;
        tig.Tips_Show("請在學生信息視圖或課程信息視圖下進行此操作S禄省!吟策!");
        tig.exec();
        Show_Label2("查詢失斎迨俊的止!");
    }
}

在表格視圖中直接對信息進行修改(原數(shù)據(jù)也進行改變)

  • 在構造函數(shù)中我們已經(jīng)鏈接了一個信號槽函數(shù)
    connect(ui->tableView->itemDelegate(),&QAbstractItemDelegate::closeEditor,this,&MainWindow::on_ShowInfotableView_changed); //信號與槽進行連接(后續(xù)可在tabelView中直接修改)
  • 而其中的==槽函數(shù)==MainWindow::on_ShowInfotableView_changed()代碼如下:
void MainWindow::on_ShowInfotableView_changed()
{
    QModelIndex index = ui->tableView->currentIndex();
    int col=index.column();

    Student & temp_ss=m_students.GetStudent(m_row);
    QVariant data;//數(shù)據(jù)

    switch(m_View_kind)
    {
    case 0://學生信息視圖
    {
        data=studentTableView->data(index);
        switch(col)
        {
        case 0: //學號
            temp_ss.s_ID=data.toString();
            break;
        case 1: //姓名
            temp_ss.s_Name=data.toString();
            break;
        case 2: //班級
            temp_ss.s_class=data.toString();
            break;
        case 3: //電話
            temp_ss.ph_number=data.toString();
            break;
        case 4: //生日
            temp_ss.birthday=data.toDate();
            break;
        case 5: //住址
            temp_ss.adress=data.toString();
            break;
        default:
            break;
        }
        Show_Table_s_changed();
        Show_Label2("修改已保存檩坚!");
        break;
    }
    case 1: //選課信息視圖
    {
        Course & temp_c=temp_ss.s_courses.GetCourse(m_row1);
        data=studentTableView->data(index);
        switch(col)
        {
        case 0: //課程編號
            temp_c.c_ID=data.toString();
            break;
        case 1: //課程名稱
            temp_c.c_Name=data.toString();
            break;
        case 2: //學分
            temp_c.credit=data.toFloat();
            break;
        case 3: //學期
            temp_c.term=data.toString();
            break;
        case 4: //教室
            temp_c.c_room=data.toString();
            break;
        case 5: //成績
            temp_c.grade=data.toFloat();
            break;
        default:
            break;
        }
        Show_Table_c_changed();
        Show_Label2("修改已保存!");
        break;
    }
    case 2: //學生信息查詢視圖
    {
        data=studentTableView->data(index);
        switch(col)
        {
        case 0: //學號
            temp_ss.s_ID=data.toString();
            break;
        case 1: //姓名
            temp_ss.s_Name=data.toString();
            break;
        case 2: //班級
            temp_ss.s_class=data.toString();
            break;
        case 3: //電話
            temp_ss.ph_number=data.toString();
            break;
        case 4: //生日
            temp_ss.birthday=data.toDate();
            break;
        case 5: //住址
            temp_ss.adress=data.toString();
            break;
        default:
            break;
        }
        Show_Table_sc_changed();
        Show_Label2("修改已保存诅福!");
        break;
    }
    case 3: //課程信息查詢視圖
    {
        Course & temp_c=temp_ss.s_courses.GetCourse(m_row1);
        data=studentTableView->data(index);
        switch(col)
        {
        case 0: //課程編號
            temp_c.c_ID=data.toString();
            break;
        case 1: //課程名稱
            temp_c.c_Name=data.toString();
            break;
        case 2: //學分
            temp_c.credit=data.toFloat();
            break;
        case 3: //學期
            temp_c.term=data.toString();
            break;
        case 4: //教室
            temp_c.c_room=data.toString();
            break;
        case 5: //成績
            temp_c.grade=data.toFloat();
            break;
        default:
            break;
        }
        Show_Table_sc_changed();
        Show_Label2("修改已保存匾委!");
        break;
    }
    }
}
  • 到這里,我們的項目就已經(jīng)完成的差不多了氓润,我們可以再添加億點點細節(jié)讓整個系統(tǒng)更加完備赂乐。

功能演示

功能介紹

  • 添加/刪除學生信息:
    在學生信息視圖下操作,刪除學生時要選中一個學生才能進行咖气;
  • 指定學生添加/刪除課程信息:
    添加操作要在學生信息視圖下選定一個學生進行添加挨措,刪除操作要在選課信息視圖下選定一個課程才能進行;
  • 可查詢學生/課程信息崩溪,并且在查詢后可直接進行修改或刪除操作:
    在學生信息視圖或課程信息視圖下進行浅役;
  • 保存/讀取文件:
    可直接讀取數(shù)據(jù)庫中的文件并保存,也可打開其他文件并另存為伶唯;
  • 可查看指定課程的學生信息觉既,并可以進行成績排序
    在特定課程學生信息視圖下進行操作;
  • 在選擇修改時才可進行修改,保護數(shù)據(jù):
    點擊“修改”選項后方可對數(shù)據(jù)進行修改瞪讼,正常情況下不可修改钧椰;

操作演示

部分操作圖片:





資源獲取

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市符欠,隨后出現(xiàn)的幾起案子嫡霞,更是在濱河造成了極大的恐慌,老刑警劉巖希柿,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秒际,死亡現(xiàn)場離奇詭異,居然都是意外死亡狡汉,警方通過查閱死者的電腦和手機娄徊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盾戴,“玉大人寄锐,你說我怎么就攤上這事〖夥龋” “怎么了橄仆?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長衅斩。 經(jīng)常有香客問我盆顾,道長,這世上最難降的妖魔是什么畏梆? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任您宪,我火速辦了婚禮,結(jié)果婚禮上奠涌,老公的妹妹穿的比我還像新娘宪巨。我一直安慰自己,他們只是感情好溜畅,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布捏卓。 她就那樣靜靜地躺著,像睡著了一般慈格。 火紅的嫁衣襯著肌膚如雪怠晴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天浴捆,我揣著相機與錄音蒜田,去河邊找鬼。 笑死汤功,一個胖子當著我的面吹牛物邑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼色解,長吁一口氣:“原來是場噩夢啊……” “哼茂嗓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起科阎,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤述吸,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后锣笨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蝌矛,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年错英,在試婚紗的時候發(fā)現(xiàn)自己被綠了入撒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡椭岩,死狀恐怖茅逮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情判哥,我是刑警寧澤献雅,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站塌计,受9級特大地震影響挺身,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜锌仅,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一章钾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧技扼,春花似錦伍玖、人聲如沸嫩痰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽串纺。三九已至丽旅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間纺棺,已是汗流浹背榄笙。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留祷蝌,地道東北人茅撞。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親米丘。 傳聞我的和親對象是個殘疾皇子剑令,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

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