Qt是什么好玩的

  Qt是1991年奇趣科技开发的一个跨平台的c++图形用户界面应用程序框架,它除了能提供给应用程序开发者建立图形用户界面所需要的功能外,还继承了很多第三方资源,如数据库、网络/多线程编程等,因此Qt既可以开发GUI程序,也可用于开发非GUI程序。

  跟Qt放在一起讨论的是Qt Creator,它是用于Qt开发的轻量级跨平台继承开发环境,该IDE集成了c++代码编辑器,可视化调试器,源代码管理、项目构建个管理等。若想学习Qt编程,我推荐跟着狄泰唐老师的课程学习。

  Qt作为一个应用程序框架,其设计思想有很多值得深入学习的地方。几易其主的Qt至今仍占有一席之地,也足矣证明这点。很多人说这是一个看脸的世界,我不否认,Android就是一个很好的例子,随之,“学习Qt不如学习Android”的言论大行其道。但是渐渐地我发现,此言差矣。学习Qt不如学习Android的看法大都出自于之前开发诺基亚塞班的软件工程师,事实上,Qt的价值依旧存在。当然啦,它不是体现在手机平板这样的消费类电子,而是在工业,或者医疗,甚至是汽车电子中。试想,作为一个工业控制系统,有必要去移植如此庞大的安卓?所以还是有很多公司更愿意选择选择ARM + Linux + Qt这样的产品设计的。这些是站在毕业一年,在深圳工作一年的角度的看法。

  Qt是用c++语言开发的,那必须得面向对象。回顾前面http://blog.csdn.net/qq_29344757/article/details/77817321写的程序中,显然是面向过程的设计流程。操作系统提供了创建用户界面所需要各个函数,通过调用这些功能不一的函数即可创建出界面元素。面向过程的弊端是:当GUI程序稍微大型,程序的开发效率低且不易维护。面向对象的思想更适合于GUI程序的设计。

  用面向对象的思想看待GUI界面元素,即GUI用户界面是由各种不相同的对象组成的,如主窗口对象、菜单对象、按钮对象等等。将界面元素定义为对应的类,通过抽象和封装可以隐藏界面元素的细节。下来对前面的程序进行面向对象化。

1. 面向对象的GUI程序设计

1.1 构建widget基类

  widget类是用于描述各种窗口元素(主窗口、窗口内元素)的基类:

//Widget.h
#pragma once  //防止重复包含
#include <windows.h>

class Widget{
protected:
    HWND m_hwnd;                    //widget的句柄
    Widget* m_parent;               //该元素所属的父类元素
                                    //例如主窗口内的按钮,按钮的m_parent为主窗口,
                                    //主窗口的m_parent为NULL

public:
    Widget();                       //构造函数,构造主窗口时用
    Widget(Widget* parent);         //带参构造函数,构造主窗口内元素时用
    HWND hwnd();                    //返回widget的句柄
    Widget* parent();               //返回widget的parent
};

//Widget.cpp
#include "Widget.h"
Widget::Widget()
{
    m_parent = NULL;
}

Widget::Widget(Widget* parent)
{
    m_parent = parent;
}

HWND Widget::hwnd()
{
    return m_hwnd;
}

Widget* Widget::parent()
{
    return m_parent;
}
1.2 构建主窗口类
//MainWindows.h
#pragma once
#include "Widget.h"

class MainWindows : public Widget //继承于Widget
{
protected:
    static const wchar_t STYLE_NAME[];

    //定义主窗口
    BOOL DefineMainWindows(HINSTANCE hInstance);

    //创建主窗口
    void CreateMainWindows(HINSTANCE hInstance);

    //主窗口消息处理函数
    static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);

public:
    MainWindows(HINSTANCE hInstance, const wchar_t* title);
    void show();
};

#include "MainWindow.h"
const wchar_t MainWindow::STYLE_NAME[] = L"Win";

//主窗口构造函数,实现定义/创建主窗口
MainWindow::MainWindow(HINSTANCE hInstance, const wchar_t* title) : Widget(NULL)
{
    DefineMainWindows(hInstance);
    CreateMainWindows(hInstance);
}

//显示主窗口
void MainWindow::show()
{
    ShowWindow(m_hwnd, SW_SHOWNORMAL); // 显示窗口
    UpdateWindow(m_hwnd);              // 刷新窗口
}

//定义主窗口
BOOL MainWindow::DefineMainWindow(HINSTANCE hInstance)
{
    static WNDCLASS WndClass = {0}; // 系统结构体类型
                                    // 用于描述窗口样式
    WndClass.style         = 0;
    WndClass.cbClsExtra    = 0;
    WndClass.cbClsExtra    = 0;
    WndClass.hbrBackground = (HBRUSH)(COLOR_WINDOW);          // 定义窗口背景色
    WndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);     // 定义鼠标样式
    WndClass.hIcon         = LoadIcon(NULL, IDI_APPLICATION); // 定义窗口左上角图标
    WndClass.hInstance     = hInstance;                       // 定义窗口式样属于当前应用程序
    WndClass.lpfnWndProc   = WndProc;                         // 窗口消息处理函数
    WndClass.lpszClassName = STYLE_NAME;                      // 窗口样式名
    WndClass.lpszMenuName  = NULL;

    // 将定义好的窗口式样注册到系统
    return RegisterClass(&WndClass);
}

//创建主窗口
void MainWindow::CreateMainWindow(HINSTANCE hInstance, const wchar_t* title)
{
    //返回主窗口的句柄,赋给基类的m_hwnd成员
    m_hwnd = CreateWindow(STYLE_NAME,            // 通过定义好的窗口式样创建主窗口
                          title,                 // 主窗口标题
                          WS_OVERLAPPEDWINDOW,   // 创建后主窗口的显示风格
                          CW_USEDEFAULT,         // 主窗口左上角 x 坐标
                          CW_USEDEFAULT,         // 主窗口左上角 y 坐标
                          CW_USEDEFAULT,         // 主窗口宽度
                          CW_USEDEFAULT,         // 主窗口高度
                          NULL,                  // 父窗口
                          NULL,                  // 窗口菜单栏
                          hInstance,             // 主窗口属于当前应用程序
                          NULL);                 // 窗口参数
}

//主窗口的消息处理函数
LRESULT CALLBACK MainWindow::WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch(message)
    {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    case WM_COMMAND:
        if (HIWORD(WM_COMMAND) == BN_CLICKED)
        {
            MessageBox(hwnd, L"Hello Button!", L"Message", 0);
        }break;
    }
    // 调用系统提供的默认消息处理函数
    return DefWindowProc(hwnd, message, wParam, lParam);
}
1.3 构建按钮类
//PushButton.h
#pragma once
#include "Widget.h"

class PushButton : public Widget
{
public:
    PushButton(Widget* win, const wchar_t *text);
};

#include "PushButton.h"

// 构造函数创建按钮
PushButton::PushButton(Widget* win, const wchar_t* text)
{
    HINSTANCE hInstance = (HINSTANCE)GetWindowLong(win->hwnd(), GWL_HINSTANCE);

    //返回按钮的句柄
    m_hwnd = CreateWindow(L"button",                               // 通过系统预定义式样创建窗口元素
                          text,                                    // 窗口元素标题
                          WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,   // 窗口元素的显示风格
                          50,                                      // 窗口元素在窗口中的左上角 x 坐标
                          50,                                      // 窗口元素在窗口中的左上角 y 坐标
                          200,                                     // 窗口元素的宽度
                          60,                                      // 窗口元素的高度
                          win->hwnd(),                             // 窗口元素所在的父窗口
                          (HMENU)this,                             // 窗口元素 ID 值
                          hInstance,                               // 窗口元素属于当前应用程序
                          NULL);                                   // 窗口元素参数
}
1.4 构建消息处理类
#pragma once
#include <windows.h>

class Application
{
public:
    Application(HINSTANCE hInstance, LPSTR lpCmdLine);
    bool exec();
};

//Application.cpp
#include "Application.h"

Application::Application(HINSTANCE hInstance, LPSTR lpCmdLine)
{
}

bool Application::exec()
{
    MSG Msg = {0};

    // 进入消息循环
    while( GetMessage(&Msg, NULL, NULL, NULL) )
    {
        // 翻译并转换系统消息
        TranslateMessage(&Msg);
        // 分发消息到对应的消息处理函数
        DispatchMessage(&Msg);
    }

    return TRUE;
}
1.5 main函数

  在main.cpp中,调用上面封装的类:

#include <windows.h>
#include "Application.h"
#include "MainWindow.h"
#include "PushButton.h"

BOOL WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    //定义接收消息的类
    Application a(hInstance, lpCmdLine);

    //定义/创建主窗口
    MainWindow w(hInstance, L"Main Window");

    //创建窗口内按钮元素
    PushButton b(&w, L"My Button");

    //显示
    w.show();

    //进入接收消息循环
    return a.exec();
}

  只要定义好所有界面元素的类,在main函数中只要将这些类组合起来即可构建GUI程序了,多么简单。但是关键难点在于这些类的构造。Qt就是为解决这个难点而应运而生的一套GUI元素的库,它将不同操作系统的GUI细节封装于类的内部,同样遵循经典的GUI程序设计原理:界面元素 + 消息处理。

2. 第一个Qt程序

#include <QApplication>
#include <QMainWindow>
#include <QPushButton>

int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    QMainWindow w;
    QPushButton b(&w);

    b.setText("hello Qt");

    w.show();

    return a.exec();
}

  在Qt开发环境安装完毕的Linux操作系统上,进入源文件目录:
这里写图片描述

$ qmake -project   //根据目录中的源码生成工程文件“目录名.pro”
$ qmake                //生成Makefile文件
$ make             //编译

运行:
这里写图片描述

  由此证明,Qt上GUI程序设计的封装实现是跟前面封装Window的API是类似的。在源码目录下执行”qmake -project”生成的.pro文件可以直接用Qt的集成开发环境Qt Creator打开。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值