QT_for_linux

第一个QT应用程序

  • 重点掌握开发流程

    (1)创建工程目录

    mkdir Hello #每个QT程序都要放在一个独立的工程目录下

    (2)进入工程目录编写源代码

    vi main.cpp #语法和C++保持基本一致,但使用QT的类库不再是标准C++的库

    #include
    #include
    int main(int argc,char** argv)
    {
    //创建QT应用程序对象
    QApplication app(argc,argv);

    //创建标签控件
    QLabel label(“Hello Qt!”);

    //显示标签控件
    label.show();

    //让应用程序进入事件
    return app.exec();

    }

    (3)构建工程

    qmake -prohect #生成工程文件Hello.pro,并在文件中添加构建选项,QT += widgets

    (4)创建Makefile

    qmake #可以根据上一步的工程文件自动生成Makefile

    (5)编译连接

    make #执行即可完成编译与链接

    (6)测试

    ./Hello #运行,默认名字与工程名字一致

QT中文编码

  • QT内部使用unicode编码,通常是UTF-16

  • QT的优化UTF-8转换为UTF-16

  • 通过QTextCodec编码转换

    QTextCodec *coder = QTextCodec::codeForName(“GBK”);
    QString string = codec->toUnicode(“GBK编码的中文字符串”);

    #include
    #include
    #include
    #include

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);

    QTextCodec *coder = QTextCodec::codecForName(“GBK”);

    QLabel label(coder->toUnicode(“我是标签”));

    label.show();

    QPushButton button(coder->toUnicode(“我是按钮”));

    button.show();

    return a.exec();
    }

父窗口

  • 创建控件时,可以指定停靠再某个父窗口上面,这时控件将作为子窗口

  • Qwidget及其子类的对象可以作为其它控件的父窗口

  • 常用的父窗口类又如下三个:

  • QWidget

  • QMainWindow(主窗口) //QWidget的直接子类

  • QDialog(对话框) //QWidget的直接子类

  • 父窗口的析构函数回自动销毁其所有的子窗口对象,因此即使子窗口对象时通过new操作符动态创建的,可以不显示的执行delete,而且不用担心内存泄漏问题,只要保证父窗口对象被正确销毁,其子窗口也将随之被销毁。

  • 设置窗口的位置和大小

    void move(int x,int y);
    void resize(int w,int h);

例子

#include
#include
#include
#include
#include
#include
#include

int main(int argc,char** argv){
QApplication app(argc,argv);
QTextCodec *codec = QTextCodec::codecForName(“UTF-8”);
//父窗口定义
QDialog parent;
parent.move(50,50);
parent.resize(320,240);

//创建标签控件,停靠再父窗口上面  
QLabel label((codec->toUnicode("我是标签")),&parent);  
label.move(20,40);  

//创建按钮控件,停靠在父窗口上边  
QPushButton button((codec->toUnicode("我是标签")),&parent);  
button.move(20,100);  
button.resize(80,80);  

parent.show();  
return app.exec();  

}
-——————————

#include
#include
#include
#include
#include
#include
#include

int main(int argc,char** argv){
QApplication app(argc,argv);
QTextCodec *codec = QTextCodec::codecForName(“UTF-8”);
//父窗口定义
QDialog parent;
parent.move(50,50);
parent.resize(320,240);

//创建标签控件,停靠再父窗口上面  
QLabel label((codec->toUnicode("我是标签")),&parent);  
label.move(20,40);  

//创建按钮控件,停靠在父窗口上边  
QPushButton button((codec->toUnicode("我是按钮")),&parent);  
button.move(20,100);  
button.resize(80,80);  

//使用对象指针的形式  
//new对象如果指定了父窗口指针,可以不写delete,在父窗口对象销毁时,它会自动被销毁。  
QPushButton\* button2 = new QPushButton((codec->toUnicode("我也是按钮")),&parent);  
button2->move(170,100);  
button2->resize(80,80);  

parent.show();//父窗口显示,上面停靠的控件也将一起显示  


return app.exec();  

}

信号和槽

  • 信号和槽是QT自行定义的一种通信机制,实现对象之间的数据交互。

  • 当用户或系统触发了一个动作,导致某个控件的状态发生了改变,该控件就会发射一个信号,即调用其类中一个特定的成员函数(信号),同时还有可能携带有必要的参数。

  • 槽和普通的成员函数几乎没有太多区别,可以是公有的、保护的或私有的,可以被重载,也可以被覆盖,其参数可以是任意类型,并可以像普通成员函数一样调用

  • 槽函数与普通成员函数的差别并不在于其语法特性,而在于其功能。槽函数更多体现为对某种特定信号的处理,可以将槽和其他对象信号建立连接,这样当发射信号时,槽函数将被触发和执行,进而来完成具体功能。

  • 型号函数

    class XX:public QObject{
    Q_OBJECT//宏,moc
    signals:
    void signal_func(..); //信号函数
    };
    //信号函数只需声明,不能写定义

  • 槽函数

    class XX:public QObject{
    Q_OBJECT//moc原对象编译器
    public slots:
    void slot_func(..){..}//槽函数
    };
    //槽函数可以连接到某个信号上,当信号被发射时,槽函数将被触发和执行,另外槽函数也可以当作普通的成员函数直接调用。

  • 信号和槽的连接

    QObject::connect(const QOject *sender,const char * signal,const QObject * receiver,const char * method);
    //参数
    sender:信号发送对象指针
    signal:要发送的信号函数,可以使用”SIGNAL(..)”宏进行类型转换
    receiver:信号的接收对象指针
    method:接收信号要执行的槽函数,可以使用”SLOT(..)”宏进行类型转换

案例

创建Qt应用程序,包含标签和按钮两个控件,实现点击按钮关闭标签

  • 按钮点击时发送信号:clicked()
  • 实现标签关闭功能的槽:close()

#include
#include
#include
#include
#include

int main(int argc,char **argv)
{
QApplication app(argc,argv);
QTextCodec *codec = QTextCodec::codecForName(“UTF-8”);

QDialog parent;  
parent.resize(320,240);  

QLabel label(codec->toUnicode("我是标签"),&parent);  
label.move(50,40);  

QPushButton button(codec->toUnicode("我是按钮"),&parent);  
button.move(50,140);  
QPushButton button1(codec->toUnicode("结束"),&parent);  
button1.move(200,140);  

//点击按钮关闭标签  
QObject::connect(&button,SIGNAL(clicked(void)),&label,SLOT(close(void)));  


//点击按钮关闭程序  
//1. QObject::connect(&button1,SIGNAL(clicked(void)),&app,SLOT(closeAllWindows(void)));  
//2. QObject::connect(&button1,SIGNAL(clicked(void)),&app,SLOT(quit(void)));  
//3. QObject::connect(&button1,SIGNAL(clicked(void)),&parent,SLOT(close(void)));  

parent.show();  
return app.exec();  

}

信号和槽连接的语法要求

  • 信号和槽参数要一致

    QObject::connect(A,SIGNAL(sigfun(int)),B,SLOT(slotfun(int))); //OK
    QObject::connect(A,SIGNAL(sigfun(int)),B,SLOT(slotfun(int,int))); //error

  • 可以带有缺省参数

    QObject::connect(A,SIGNAL(sigfun(int)),B,SLOT(slotfun(int,int=0))); //OK

  • 信号函数的参数可以多于槽函数

    QObject::connect(A,SIGNAL(sigfun(int,int)),B,SLOT(slotfun(int)))); //OK

  • 一个信号可以被连接到多个槽

    QObject::connect(A,SIGNAL(sigfun(int)),B1,SLOT(slotfun(int)))); //OK
    QObject::connect(A,SIGNAL(sigfun(int)),B2,SLOT(slotfun(int)))); //OK
    //触发的顺序不确定

  • 多个信号也可以连接到同一个槽

    QObject::connect(A1,SIGNAL(sigfun1(int)),B,SLOT(slotfun(int)))); //OK
    QObject::connect(A2,SIGNAL(sigfun2(int)),B,SLOT(slotfun(int)))); //OK

  • 两个信号可以直接连接(信号级联)

    QObject::connect(A1,SIGNAL(sigfun2(int)),A2,SLOT(sigfun2(int)))); //OK

  • 案例

    创建QT应用程序,包含滑块(QSlider)和选值框(QSpinBox),通过信号和槽的机制,保持同步运行

    #include
    #include
    #include
    #include
    #include
    #include
    #include

    int main(int argc,char **argv)
    {
    QApplication app(argc,argv);
    QDialog parent;
    parent.resize(320,240);

    //创建水平滑块
    QSlider slider(Qt::Horizontal,&parent);
    slider.move(20,100);
    slider.setRange(0,200);

    //创建选值框
    QSpinBox spin(&parent);
    spin.move(220,100);
    spin.setRange(0,200);

    //滑块滑动,选值框随之改变
    QObject ::connect(&slider,SIGNAL(valueChanged(int)),&spin,SLOT(setValue(int)));

    //改变选值,滑块改变
    QObject ::connect(&spin,SIGNAL(valueChanged(int)),&slider,SLOT(setValue(int)));

    parent.show();
    return app.exec();
    }

面向对象的Qt编程

  • 基于对象的Qt编程,有限制

  • 通过面向对象的编程思想实现加法计算器

  • 案例

    计算器实现

    calcuator.h

    #ifndef CALCULATOR_H
    #define CALCULATOR_H

    #include
    #include
    #include
    #include //行编辑控件
    #include //水平布局器
    #include //验证器

    class Calculator : public QDialog
    {
    Q_OBJECT //mocQt语法扩展
    private:
    QLineEdit* m_editX;
    QLineEdit* m_editY;
    QLineEdit* m_editZ;
    QLabel* m_label;
    QPushButton* m_button;
    public:
    Calculator(void);
    ~Calculator();
    public slots:
    //使能的能耗按钮的槽操作数
    void enableButton(void);
    void calcClicked(void);
    };

    #endif // CALCULATOR_H

    calculator.cpp

    #include “calculator.h”

    Calculator::Calculator(void)
    {

    //界面初始化  
    setWindowTitle("计算器");  
    //左操作数,this即为当前父窗口指针  
    m\_editX = new QLineEdit(this);  
    //设置文本对齐:右对齐  
    m\_editX->setAlignment(Qt::AlignRight);  
    //设置数字验证器,只能输入数字形式内容  
    m\_editX->setValidator(new QDoubleValidator(this));  
    
    //右操作数  
    m\_editY = new QLineEdit(this);  
    //设置文本对齐:右对齐  
    m\_editY->setAlignment(Qt::AlignRight);  
    //设置数字验证器,只能输入数字形式内容  
    m\_editY->setValidator(new QDoubleValidator(this));  
    
    //显示结果  
    m\_editZ = new QLineEdit(this);  
    m\_editZ->setAlignment(Qt::AlignRight);  
    m\_editZ->setReadOnly(true);//设置为只读  
    
    //"+"  
    m\_label = new QLabel("+",this);  
    //"="  
    m\_button = new QPushButton("=",this);  
    m\_button->setEnabled(false); //设置禁用  
    
    
    //创建布局器:自动调整每个控件的大小和位置  
    QHBoxLayout\* layout = new QHBoxLayout(this);  
    //按水平方向,依次添加控件到布局器中  
    layout->addWidget(m\_editX);  
    layout->addWidget(m\_label);  
    layout->addWidget(m\_editY);  
    layout->addWidget(m\_button);  
    layout->addWidget(m\_editZ);  
    //设置布局器  
    setLayout(layout);  
    
    //信号和槽函数连接  
    //左右操作数文本改变时,发送信号textChanged()  
    connect(m\_editX,SIGNAL(textChanged(QString)),this,SLOT(enableButton(void)));  
    connect(m\_editY,SIGNAL(textChanged(QString)),this,SLOT(enableButton(void)));  
    
    //点击按钮,发送信号clicked  
    connect(m\_button,SIGNAL(clicked(void)),this,SLOT(calcClicked(void)));  
    

    }

    Calculator::~Calculator()
    {

    }

    void Calculator::enableButton(void){
    bool bX0k = 0,bY0k = 0;
    //text:获取输入文本(QString)
    //toDouble():QString转换为double,参数保存转换是否成功结果
    m_editX->text().toDouble(&bX0k);
    m_editY->text().toDouble(&bY0k);

    //左右操作数都为有效数字,则使能等号按钮,否则设置禁用
    m_button->setEnabled(bX0k && bY0k);
    }
    //计算结果和显示的槽函数
    void Calculator::calcClicked(void){

    double res = m\_editX->text().toDouble()+m\_editY->text().toDouble();  
    
    //number():将double转换为QString  
    QString str = QString::number(res);  
    //显示字符串形式结果  
    m\_editZ->setText(str);  
    

    }

    mian.cpp

    #include “calculator.h”
    #include

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    Calculator w;
    w.show();

    return a.exec();
    }

参考文献

。。