GNU开发工具——CMake工程实践

GNU开发工具——CMake工程实践

一、CMake构建Qt工程

1、Qt工程源码

创建Migration目录,在目录下创建main.cpp文件:

#include <QApplication>
#include <QLabel>

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QLabel label(QString("Hello Qt%1!").arg(int(QT_VERSION >> 16)));
    label.setAlignment(Qt::AlignCenter);
    label.resize(200, 100);
    label.show();
    return app.exec();
}

2、Qt4和Qt5兼容宏

编写兼容Qt4和Qt5的CMake宏,QtMigration.cmake文件如下:

# 定义宏QT_USE_MODULES
macro(QT_USE_MODULES _target)
    # Enable AUTOMOC
    set_target_properties(${_target} PROPERTIES AUTOMOC TRUE)
    # Local variables
    set(_modules_qt4)
    set(_modules_qt5)
    # Prepare modules
    foreach(_module ${ARGN})
        list(APPEND _modules_qt4 Qt${_module})
        list(APPEND _modules_qt5 ${_module})
        if(_module MATCHES "Gui")
            list(APPEND _modules_qt5 "Widgets")
        endif(_module MATCHES "Gui")
    endforeach(_module ${ARGN})
    list(REMOVE_DUPLICATES _modules_qt4)
    list(REMOVE_DUPLICATES _modules_qt5)
    # Find Qt libraries
    find_package(Qt5 QUIET COMPONENTS ${_modules_qt5})
    if(Qt5_FOUND)
        qt5_use_modules(${_target} ${_modules_qt5})
    else(Qt5_FOUND)
        find_package(Qt4 QUIET COMPONENTS ${_modules_qt4})
        if(Qt4_FOUND OR QT4_FOUND)
            include(${QT_USE_FILE})
            include_directories(${QT_INCLUDES})
            add_definitions(${QT_DEFINITIONS})
            target_link_libraries(${_target} ${QT_LIBRARIES})
        endif(Qt4_FOUND OR QT4_FOUND)
    endif(Qt5_FOUND)
endmacro(QT_USE_MODULES)

3、CMakeLists.txt编写

编写工程CMakeLists.txt文件,内容如下:

cmake_minimum_required(VERSION 2.8.9)
project(Migration)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR})
aux_source_directory(. SRC_LIST)
add_executable(${PROJECT_NAME} ${SRC_LIST})
include(QtMigration.cmake)
QT_USE_MODULES(${PROJECT_NAME} Core Gui)

4、构建工程

Migration工程内创建build目录,进入build目录,进行构建。

cmake ..
make

5、CMake的Qt相关变量

对于Qt4,使用FIND_PACKAGE后,会生成有效的Qt4_FOUND,QT_USE_FILE,QT_INCLUDES,QT_LIBRARIES变量。

FIND_PACKAGE(Qt4 REQUIRED Core Gui)
if(Qt4_FOUND)
    INCLUDE(${QT_USE_FILE})
    INCLUDE_DIRECTORIES(${QT_INCLUDES})
    TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${QT_LIBRARIES})
endif()

对于Qt5,使用FIND_PACKAGE后,会生成有效的Qt5_FOUND,Qt5Core_INCLUDE_DIRS,Qt5Xml_INCLUDE_DIRS,Qt5Gui_INCLUDE_DIRS,Qt5Widgets_INCLUDE_DIRS,Qt5OpenGL_INCLUDE_DIRS,Qt5Widgets_LIBRARIES,Qt5Core_LIBRARIES,Qt5Gui_LIBRARIES,Qt5Xml_LIBRARIES,Qt5OpenGL_LIBRARIES等相应模块的变量。

FIND_PACKAGE(Qt5 REQUIRED Core Gui Widgets OpenGL Xml)
if(Qt5_FOUND)
    INCLUDE_DIRECTORIES(${Qt5Core_INCLUDE_DIRS} ${Qt5Xml_INCLUDE_DIRS}
        ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5OpenGL_INCLUDE_DIRS})
    #定义QT_LIBRARIES
    SET(QT_LIBRARIES ${Qt5Widgets_LIBRARIES} ${Qt5Core_LIBRARIES}
        ${Qt5Gui_LIBRARIES} ${Qt5Xml_LIBRARIES} ${Qt5OpenGL_LIBRARIES})
    TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${QT_LIBRARIES})
endif(Qt5_FOUND)

开启MOC支持
set(CMAKE_AUTOMOC ON)
开启RCC支持
set(CMAKE_AUTORCC ON)
开启UIC支持
set(CMAKE_AUTOUIC ON)
设置Qt安装目录:
set(CMAKE_PREFIX_PATH "Qt to path ") //bin lib include目录层

二、QtCreator使用CMake构建Qt工程

1、QtCreator创建Qt工程(CMake构建)

选择新建工程,创建一个Plain C++ Application。

选择使用CMake构建工程:

选择使用的Qt Kits版本:

2、增加C++类

选择菜单栏新建文件按钮,选择Files and Classes,C++ Class。

填写创建C++类的名称BarModelMapperChartWidget:

选择创建类文件所在位置,点击浏览按钮:

点击新建目录按钮创建ChartWidget目录,选择ChartWidget。
BarModelMapperChartWidget.h文件如下:

#ifndef BARMODELMAPPERCHARTWIDGET_H
#define BARMODELMAPPERCHARTWIDGET_H

#include <QWidget>
#include <QtCharts/QChart>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
#include <QtCharts/QVXYModelMapper>
#include <QtCharts/QBarSeries>
#include <QtCharts/QBarSet>
#include <QtCharts/QVBarModelMapper>
#include <QtWidgets/QHeaderView>
#include <QtCharts/QBarCategoryAxis>
#include <QHBoxLayout>

QT_CHARTS_USE_NAMESPACE

/**
 * @brief 柱状图ModelMapper报表界面类
 */
class BarModelMapperChartWidget : public QWidget
{
    Q_OBJECT
public:
    explicit BarModelMapperChartWidget(QWidget *parent = NULL);
    /**
     * @brief 初始化ModelMapper
     * @param model
     */
    void initModelMapper(QAbstractTableModel* model);
private:
    QChart* m_chart;//报表组件
    QChartView* m_chartView;//报表视图组件
};

#endif // BARMODELMAPPERCHARTWIDGET_H

BarModelMapperChartWidget.cpp文件如下:

#include "BarModelMapperChartWidget.h"

BarModelMapperChartWidget::BarModelMapperChartWidget(QWidget *parent) : QWidget(parent)
{
    m_chart = new QChart;
    m_chart->setAnimationOptions(QChart::AllAnimations);

    m_chartView = new QChartView(m_chart);
    m_chartView->setRenderHint(QPainter::Antialiasing);
    QHBoxLayout* layout = new QHBoxLayout;
    layout->addWidget(m_chartView);
    setLayout(layout);
}

void BarModelMapperChartWidget::initModelMapper(QAbstractTableModel *model)
{
    QBarSeries *series = new QBarSeries;
    int first = 3;
    int count = 5;
    QVBarModelMapper *mapper = new QVBarModelMapper(this);
    mapper->setFirstBarSetColumn(1);
    mapper->setLastBarSetColumn(4);
    mapper->setFirstRow(first);
    mapper->setRowCount(count);
    // 设置mapper的数据集对象
    mapper->setSeries(series);
    // 设置mapper对应的数据Model
    mapper->setModel(model);
    m_chart->addSeries(series);

    QStringList categories;
    categories << "April" << "May" << "June" << "July" << "August";
    QBarCategoryAxis *axis = new QBarCategoryAxis();
    axis->append(categories);
    m_chart->createDefaultAxes();
    m_chart->setAxisX(axis, series);
}

创建TableModel类:

TableModel.h文件如下:

#ifndef TABLEMODEL_H
#define TABLEMODEL_H

#include <QAbstractTableModel>
#include <QHash>
#include <QRect>
#include <QVector>
#include <QTime>
#include <QColor>
#include <QTimer>
/**
 * @brief 数据模型
 */
class TableModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    explicit TableModel(QObject *parent = 0);
    virtual ~TableModel();
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
    Qt::ItemFlags flags(const QModelIndex &index) const;
    /**
     * @brief 生成数据
     */
    void generateData();
private slots:
    /**
     * @brief 定时器超时信号的槽函数
     */
    void onGenerateData();
private:
    QList<QVector<qreal> * > m_data;//模型数据容器
    int m_columnCount;//列数
    int m_rowCount;//行数
    QTimer timer;//定时器
};

#endif // TABLEMODEL_H

TableModel.cpp文件如下:

#include "TableModel.h"

TableModel::TableModel(QObject *parent) : QAbstractTableModel(parent)
{
    m_columnCount = 6;
    m_rowCount = 12;
    // 创建数据容器并初始化
    for (int i = 0; i < m_rowCount; i++)
    {
        QVector<qreal>* dataVec = new QVector<qreal>(m_columnCount);
        for (int k = 0; k < dataVec->size(); k++)
        {
            dataVec->replace(k, 100 + qrand() % 50);
        }
        m_data.append(dataVec);
    }
    // 每隔2秒超时
    timer.start(2000);
    connect(&timer, SIGNAL(timeout()), this, SLOT(onGenerateData()));
}

TableModel::~TableModel()
{
    qDeleteAll(m_data);
}

int TableModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_data.count();
}

int TableModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_columnCount;
}

QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal)
        return QString("201%1").arg(section);
    else
        return QString("%1").arg(section + 1);
}

QVariant TableModel::data(const QModelIndex &index, int role) const
{
    if (role == Qt::DisplayRole)
    {
        return m_data[index.row()]->at(index.column());
    }
    else if (role == Qt::EditRole)
    {
        return m_data[index.row()]->at(index.column());
    }

    return QVariant();
}

bool TableModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (index.isValid() && role == Qt::EditRole)
    {
        m_data[index.row()]->replace(index.column(), value.toDouble());
        emit dataChanged(index, index);
        return true;
    }
    return false;
}

Qt::ItemFlags TableModel::flags(const QModelIndex &index) const
{
    return QAbstractItemModel::flags(index) | Qt::ItemIsEditable;
}

void TableModel::generateData()
{
    // 生成新的数据
    for (int i = 0; i < m_rowCount; i++)
    {
        for (int k = 0; k < m_data.at(i)->size(); k++)
        {
            m_data.at(i)->replace(k, 100 + qrand() % 50);
        }
    }
    QModelIndex leftTop = index(0, 0);
    QModelIndex rightBottom = index(m_rowCount - 1, m_columnCount - 1);
    // 生成新数据后发送模型数据发生变化的信号dataChanged
    emit dataChanged(leftTop, rightBottom);
}

void TableModel::onGenerateData()
{
    generateData();
}

增加MainWindow类:

MainWindow.h文件如下:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QWidget>
#include <QHBoxLayout>
#include <QTableView>
#include "ChartWidget/BarModelMapperChartWidget.h"
#include "Model/TableModel.h"

/**
 * @brief 程序主界面类
 */
class MainWindow : public QWidget
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = NULL);

private:
    BarModelMapperChartWidget* m_barModelMapperChartWidget;//报表组件
    QTableView* m_tableView;//表格视图组件
    TableModel* m_model;//表格模型
};

#endif // MAINWINDOW_H

MainWindow.cpp文件如下:

#include "MainWindow.h"

MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{
    m_model = new TableModel();
    m_barModelMapperChartWidget = new BarModelMapperChartWidget(this);
    m_barModelMapperChartWidget->initModelMapper(m_model);

    m_tableView = new QTableView(this);
    m_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    m_tableView->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);

    m_tableView->setModel(m_model);
    QHBoxLayout* layout = new QHBoxLayout;
    layout->addWidget(m_tableView);
    layout->addWidget(m_barModelMapperChartWidget);
    setLayout(layout);
    resize(800, 400);
}

main.cpp文件:

#include <QApplication>
#include "MainWindow.h"

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    MainWindow w;
    w.show();
    return app.exec();
}

3、工程CMakeLists.txt文件

CMakeLists.txt文件如下:

# CMake版本约束
cmake_minimum_required(VERSION 2.8.3)
#工程名称
project(CMakeDemo)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "-fPIC")
set(CMAKE_BUILD_TYPE "Debug")
# 增加子目录ChartWidget的源码到变量SOURCES
aux_source_directory(ChartWidget SOURCES)
# 增加子目录Model的源码到变量SOURCES
aux_source_directory(Model SOURCES)
# 设置QT安装路径
set(CMAKE_PREFIX_PATH "/usr/local/Trolltech/Qt5.10.1/5.10.1/gcc_64")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# 开启Qt MOC
set(CMAKE_AUTOMOC ON)
#开启Qt ROC
set(CMAKE_AUTORCC ON)
# 开启Qt UIC
set(CMAKE_AUTOUIC ON)
set(QT Core Gui Widgets Charts)
# 查找Qt库
find_package(Qt5 REQUIRED ${QT})
if(Qt5_FOUND)
    include_directories(${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS}
        ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Charts_INCLUDE_DIRS})
    set(QT_LIBRARIES ${Qt5Widgets_LIBRARIES} ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Charts_LIBRARIES})
    # 增加可执行文件
    add_executable(${PROJECT_NAME} ${SOURCES} main.cpp MainWindow.cpp)
    target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES})
endif(Qt5_FOUND)

4、构建

QtCreator管理工程如下:

编译、调试可以使用QtCreator直接进行,方便快捷。
如果需要调试,必须在CMakeLists.txt设置(CMAKE_BUILD_TYPE为Debug。
set(CMAKE_BUILD_TYPE "Debug")
运行结果如下:

源码示例:https://down.51cto.com/data/2461580

原文地址:https://blog.51cto.com/9291927/2396966

时间: 2024-11-12 10:47:39

GNU开发工具——CMake工程实践的相关文章

GNU开发工具——CMake进阶

GNU开发工具--CMake进阶 一.CMake基础指令 1.cmake_minimum_required cmake_minimum_required (VERSION 2.8)cmake_minimum_required用于规定cmake程序的最低版本,可选.如果CMakeLists.txt文件中使用了高版本cmake特有的一些命令时,就需要使用cmake_minimum_required对CMake进行版本限制,提醒用户升级到相应版本后再执行cmake. 2.project project

GNU开发工具——CMake模块

GNU开发工具--CMake模块 一.find_packge高级功能 1.find_package的模式 find_package()有Module模式(基本用法)和Config模式(完全用法),其中Module模式是基础,Config模式则提供复杂高级功能.find_package是否使用Config模式可以通过下列条件判断:(1)find_package()中指定CONFIG关键字(2)find_package()中指定NO_MODULE关键字(3)find_package()中使用了不再M

GNU开发工具——CMake快速入门

GNU开发工具--CMake快速入门 一.CMake简介 不同Make工具,如GNU Make.QT的qmake.微软的MS nmake.BSD Make(pmake)等,遵循着不同的规范和标准,所执行的Makefile格式也不同.如果软件想跨平台,必须要保证能够在不同平台编译.而如果使用Make工具,必须为不同的Make工具编写不同的Makefile.CMake是一个比Make工具更高级的编译配置工具,是一个跨平台的.开源的构建系统(BuildSystem).CMake允许开发者编写一种平台无

GNU开发工具——WireShark网络分析工具

GNU开发工具--WireShark网络分析工具 一.WireShark网络分析工具简介 1.WireShark简介 Wireshark是目前全球使用最广泛的开源网络封包分析软件(前身为Ethereal),由Gerald Combs编写并于1998年以GPL开源许可证发布.网络封包分析软件的功能是撷取网络封包,并尽可能显示出最为详细的网络封包资料. 2.WireShark架构 GUI:处理所有的用户输入输出(所有窗体,对话框等)Core:核心模块,通过函数调用将其他模块连接在一起Epan:包分析

Git工程开发实践(六)——Git工程实践扩展

Git工程开发实践(六)--Git工程实践扩展 一.Git提交日志规范 1.Git提交日志模板 Git支持对每次提交的日志信息进行规范,可以通过设置提交模板实现.建立一个gitCommitTemplate文件,内容为: #commit message包含三部分,header, body和footer,其中header必选,body和footer可选. # type(<scope>): <subject> #<body> #<footer> #type字段包含

如何为Eclipse开发工具中创建的JavaWeb工程创建Servlet

在博客<在Eclipse中如何创建JavaWeb工程>中图文并茂的说明了Eclipse中创建JavaWeb工程的方法,本篇博客将告诉大家如何为Eclipse开发工具中创建的JavaWeb工程创建Servlet: 1.在Eclipse开发工具中创建的JavaWeb工程文件目录结构如下图: 说明: a).红框框定的结构用于存放Java类及其相应的包:用于存放Libraries文件夹: b).灰框框定的结构用于显示(非"存放")JavaWeb工程所依赖的JDK相关的jar包: c

iOS平台软件开发工具(一)-新建的工程使用CocoaPods工具集成第三方框架

CocoaPods是一款集合了上千个第三方开源库的开发工具,能够大幅度的提升团队项目的开发效率,降低时间成本. 那么就看一下CocoaPods这个工具在项目中的使用体现吧. 我们马上用ASIHTTPRequest第三方开源框架,说明如何在我们的项目中使用CocoaPods工具快速集成第三方开源框架. 首先,创建一个iOS平台下的空应用程序工程EmptySample. 然后,在终端中进入新建的工程目录,如图所示 结果如图所示. 在新建的工程根目录下,使用vi命令新建Podfile文件.(注意,不用

百度地图V2.0实践项目开发工具类bmap.util.js V1.4

/** * 百度地图使用工具类-v2.0(大眾版) * * @author boonya * @date 2013-7-7 * @address Chengdu,Sichuan,China * @email [email protected] * @company KWT.Shenzhen.Inc.com * @notice 有些功能需要加入外部JS库才能使用,另外还需要申请地图JS key . * 申请地址:http://developer.baidu.com/map/apply-key.ht

linux下C++开发工具

就C++开发工具而言,与Windows下微软(VC, VS2005等)一统天下相比,Linux/Unix下C++开发,可谓五花八门,各式各样.Emacs, vi, eclipse, anjuta,kdevelop等层出不穷.Windows下,开发工具多以集成开发环境IDE的形式展现给最终用户.例如,VS2005集成了编辑器,宏汇编ml,C /C++编译器cl,资源编译器rc,调试器,文档生成工具, nmake.它们以集成方式提供给最终用户,对于初学者而言十分方便.但是,这种商业模式,直接导致用户