• QT-编码方式,信号和槽,容器窗口与事件同步,面向对象的QT编程(day2)


    一、编译方式

    1、Qt内部编码方式:unicode编码

      可以表示所有常见的文件,提供世界上几乎所有的文字的唯一编码方式。具有通用性;具有两字节和四字节标准。

      但是我们在编写代码时,不能采用unicode编码,因为unicode编码每个字符都采用两个字符表示,但是char类型只有一个字节。多余的用0表示,但是字符串的结束标志就是空,所以不能用unicode编码方式来写代码。

      查看QString帮助,可以看到,它也是提供的unicode编码。在QT中所有字符串都要转换成QString来存储,而字符是QChar(即unicode)

      查看参数为常字符串的构造函数,可以看到它使用fromUtf8()函数将我们输入的字符串(Utf-8)转换成unicode字符串。即在构造函数中,进行了编码方式转换。

      如果在不同的系统中,不经过编码转换将会发生乱码。

    例:

      将设置虚拟机与宿主机的共享文件夹,将QT下昨天编写的源文件拷贝到Linux的共享文件夹下,用在Windows下用记事本打开,再点击另存为,可以看到默认的编码方式默认为UTF-8,将其修改为ANSI(GBK编码),保存并替换,此时编码方式已经改变为GBK编码。回到Linux将共享文件替换原来的源文件。再编译将出现执行可执行程序,将出现乱码现象。GBK的编码使用fromUtf8()函数无法完成正常转换。

      

    注意:

      不同的编码方式,对中文的影响较大,因为中文的字符个数较多。但是英文基本不受编码方式影响。

    2、手动编码方式转换

    (1)QTextCodec类(最后一个字母是转换的缩写,即文本编码转换)

       

    (2)实例

      ...表示当前编辑器默认的编码方式,这里为KOI8-R。也可以直接将字符串放在第三行的参数中

      第二句表示获取一个KOI8-R的对象

      第三句表示将这种编码的字符串转换为unicode编码

      

      如果是想将GBK编码转换为unicode编码,只需将KOI8-R替换为GBK即可。

      

    注意:

      在QT5中,QString内部可以通过类型转换构造函数,将utf8编码自动转换成unicode编码。其他编码需要手动转换为unicode。


    二、信号和槽

    1、基本概念

      信号和槽是QT自行定义的一种通信机制,实现对象之间的数据交互。如:实现点击按钮,关闭标签。

      其本质就是函数的调用,一个信号发出,连接到该信号的槽函数将被执行。

    2、定义方式

    class xx{

      Q_OBJECT//元对象编译器,使不符合标准C++的语法转换成符合标准C++的语法

    signals://QT中定义的关键字

      void sig_func(..);//信号函数,信号函数只能被声明,不能被定义,因为他是执行时动态调用槽函数。

    public slots://slots为QT中定义的关键字

      void sig_func(...);//槽函数

    };

    3、建立信号和槽的连接

       使用如下的函数,它是一个静态成员函数。信号连接发生在运行期间,这一点需要注意。

     注意:

      信号函数和槽函数是字符串,即函数签名,不是函数的指针。即按字符串形式处理。

      QT提供两个宏可以将信号函数或者槽函数转换为const char*指针:

    SIGNAL(信号函数);//将信号函数转换为const char*

    SLOT(槽函数);//将槽函数转换为const char*

    参数:

      sender:信号发送的指针

      signal:信号函数

      receiver:信号接收的对象指针

      method:槽函数

     #include<QApplication>
    
    #include<QLabel>
    
    #include<QPushButton>
    
    #include<QObject> 
    
    
    
    int main(int arg,char* argv[]){
    
      QApplication app(argc,argv);
    
     
    
      QLabel label("Hello QT!");
    
      QPushButton button("关闭标签");
    
      label.show();
    
      button.show();
    
      
    
      //连接信号和槽函数
    
      QObject::connect(&button,SIGNAL(clicked()),&label,SLOT(close()));
    
    
    
      return app.exec();
    
    }

    练习:

      实现点击按钮,关闭应用

    思路:在帮助文档中查找QApplication及其基类相关可以退出或者关闭的函数,可以查找到:

      void closeAllWindows();

      和上一层基类中的

      void quit();

     #include<QApplication>
    
    #include<QLabel>
    
    #include<QPushButton>
    
    #include<QObject> 
    
     
    
    int main(int arg,char* argv[]){
    
      QApplication app(argc,argv);
    
     
    
      QLabel label("Hello QT!");
    
      QPushButton button("关闭标签");
    
      label.show();
    
      button.show();
    
      
    
      //连接信号和槽函数
    
      QObject::connect(&button,SIGNAL(clicked()),&app,SLOT(closeAllWindows()));
    
      // QObject::connect(&button,SIGNAL(clicked()),&app,SLOT(quit()));
      return app.exec();
    
    }

    4、信号和槽函数连接的语法要求

    1)一般信号和槽函数参数顺序和类型要相同

    QObject::connect(&button,SIGNAL(sig_func(int)),&app,SLOT(slot_func(int)));//ok
    
    QObject::connect(&button,SIGNAL(sig_func(int)),&app,SLOT(slot_func(intstring)));//error
     

    2)信号函数和槽函数可带有缺省参数

    QObject::connect(&button,SIGNAL(sig_func(int)),&app,SLOT(slot_func(intstring="")));//ok


    3)信号函数的参数可以多于槽函数

    QObject::connect(&button,SIGNAL(sig_func(intstring)),&app,SLOT(slot_func(int)));//ok多于的参数将被忽略

    4)一个信号可以连接到多个槽函数,信号发生时,都会被执行

    QObject::connect(&button,SIGNAL(sig_func(int)),&app1,SLOT(slot_func1(int)));//ok
    QObject::connect(&button,SIGNAL(sig_func(int)),&app2,SLOT(slot_func2(int)));//ok

    5)多个信号可以对应同一个槽函数,无论谁发了信号,槽函数都会被执行

    QObject::connect(&button1,SIGNAL(sig_func1(int)),&app,SLOT(slot_func(int)));//ok
    QObject::connect(&button2,SIGNAL(sig_func2(int)),&app,SLOT(slot_func(int)));//ok

    三、滑块类(QSlider)、微调框/选值框(QSpinbox)

    1、<案例>事件同步

    (1)滑块类

      构造函数

    槽函数

    setRange(int min,int max);//设置滑动范围
    
    setRange(int);//设置滑块位置

    信号函数

    valueChanged(int value);//滑块滑动时发送位置信号

    (2)微调框/选值框(QSpinbox)

    构造函数: 

    QSpinbox(QWidget* parent=0);

    其他:

    setRange(int minimum,int maxmum);//设置选值的范围

    槽函数:

    setValue(int val);

    信号函数:

    valueChanged(int i);发送值改变的信号
    
    valueChanged(const QString& text);
    #include<QApplication>
    
    #include<QSlider>
    
    #include<QSpinbox>
    int main(int arg,char* argv[]){  QApplication app(argc,argv);
    
     
      //创建滑块组件,并设置其属性
      QSlider slider(Qt::Horizontal);//设置为水平滑块
      
      slider.setRange(0,100);//设置范围
      
      slider.show()
    
      
      //创建选值框
    
      QSpinbox spin;
      
      spin.setRange(0,100);
    
      spin.show();
    
    
    
      //连接信号和槽函数,相互连接
    
      QObject::connect(&slider,SIGNAL(valueChanged(int)),&spin,SLOT(setValue(int)));
      QObject::connect(&spin,SIGNAL(valueChanged(int)),&slider,SLOT(setValue(int)));
    
    
      
    
      return app.exec();
    
    }

    因为信号发送和槽函数接收是动态的,所以在它们出现拼写错误时,编译不会报错,执行时才会出现问题。如果执行时出现问题可以考虑是否是这个问题造成的。

     



    三、容器窗口(父窗口)与事件同步

    1、父窗口
      如果一个组件在创建时指定了父窗口,那么他就会停靠在父窗口上面,如果不指定,就会游离在外部形成独立的窗体。

    (1)常用的父窗口类

      QWidget(绝大多数图形组件的基类,它的成员函数子类都可以使用)、QMainWindow(Q
    Widget的子类,一般是主界面使用此类)、QDialog(也是QWidget的子类,一般对话框就是用这个类)是比较常用的父窗口类
    在实际的开发中,一般使用后两者比较多。
    (2)QWidget基类中两个常用的成员函数
    resize(int x,int y);调整大小,单位为分辨率
    move(int x,int y);//调整位置

    注意:
      对于父窗口对象,起始位置是相对于屏幕左上角,如果是父窗口中的停靠组件,则相对的是父窗口的左上角。


     #include<QApplication>
    
    #include<QLabel>
    
    #include<QPushButton>
    
    #include<QObject> 
    
    #include<QWidget>//默认左上角显示,也可以使用QDialog(默认居中显示,没有最大化,最小化)和QMianWindow(默认左上角显示)类
    
     
    
    int main(int arg,char* argv[]){
    
      QApplication app(argc,argv);
    
       
      //创建一个父窗口对象
      QWidget parent;
      //设置父窗口大小,200*200像素
      parent.resize(200,200);
      //调节父窗口位置
      parent.move(300,300);
      
    
      //创建lable和button时指针停靠在parent父窗口
    
      QLabel label("Hello QT!",&parent/*指定父窗口*/);
    
      label.move(0,100);//垂直方向不变,水平方向向右移动100像素
      
    
      QPushButton button("关闭标签",&parent);
      button.move(100,100);//移动按钮
    
      //label.show();
    
      //button.show();
    
      //显示父窗口,它所包含的组件也会一起显示
      parent.show();//主窗口必须显示
      
    
      //连接信号和槽函数
    
      QObject::connect(&button,SIGNAL(clicked()),&app,SLOT(closeAllWindows()));
    
      // QObject::connect(&button,SIGNAL(clicked()),&app,SLOT(quit()));
      return app.exec();
    
    }
    补充:使用付窗口的优点
      (1)布局看起来更为美观,更容易管理
      (2)因为有时候会动态分配内存,但是可能忘记释放。使用父窗口可以不用担心这个问题,因为主窗口的析构函数会调用所有组件的析构函数,进行内存释放。





    四、面向对象的QT编程
    1、基于对象的QT编程
      因为我们是使用QT已经封装好的类,但是只能在外部使用其公有的成员,限制较大,不推荐。例如前面的的所有案例都是基于对象的编程。

    2、面向对象的QT编程
    <案例>实现加法计算器

    思路:
      

    封装一个类:

    class CalculatorDialog:public QDialog{
    
    行为:
    
      构造函数;初始化图形界面(UI)
    
      槽函数:当输入左右操作数时,使能等号按钮
    
      槽函数:点击等号按钮时调用,计算结果
    
    属性:
    
      QLineEdit
    
      QPushButton
    
      QLabel
    
    }; 
    
    
    int main(int argc,char** argv){
      QApplication app(argc,argv);
      
      CalculatorDialog cal;
      cal.show()
      
      return app.exec();
    }

    实现代码:

    //CalculatorDialog.h文件

    #ifndef __CalculatorDialog__ #define __CalculatorDialog__ #include<QDialog> #include<QLineEdit> #includeQ<PushButton> #include<QLabel> //水平布局器,用于自动调整组件的大小和位置 #include<QHBoxLayout> //验证器,输入组件只能输入数字 #include<QDoubleValidator> class CalculatorDialog:public Dialog{   Q_OBJECT //元对象,使用MOC编译器声明QT语法转换为标准C++ public:   CalculatorDialog(void); private slots:   //使能等号按钮   void enbleCalculation(void);      //计算结果   calcClicked(); private:   QLineEdit* m_editX;//左操作数   QLineEdit* m_editY;//右操作数   QPushButton* m_btnCalc;//等号按钮   QLineEdit* m_edit;//保存结果 }; #endif

    扩展:

      使用元对象编译器可以生成moc开头的文件,再将这些文件通过标准C++编译器编译。

    //CalculatorDialog.cpp文件
    
    #include "CalculatorDialog.h"
    
     
    
    //构造函数
    
    CalculatorDialog::CalculatorDialog(void){
    
      //设置标题
    
       setWindowTitle("计算器");
    
      
    
      //创建编辑框(左右操作数)
    
      m_editX =new QLineEdit(this);//this指向计算机父窗口
    
      //设置对齐方式
    
      m_editX->setAlignment(Qt::AlignRignt);//设置右对齐
    
      //设置验证器,让其只能输入数字
    
      m_editX->setValidator(new QDoubleValidator(this));
    
     
    
      m_editY =new QLineEdit(this);
    
      //设置对齐方式
    
      m_editY->setAlignment(Qt::AlignRignt);//设置右对齐
    
      //设置验证器,让其只能输入数字
    
      m_editY->setValidator(new QDoubleValidator(this));
    
     
    
      
    
      m_editZ =new QLineEdit(this);
    
      //设置对齐方式
    
      m_editZ->setAlignment(Qt::AlignRignt);//设置右对齐
    
      //输出结果只读
    
      m_editZ->setReadOnly(true);
    
     
    
      //创建等号
    
      m_btnCalc=new QPushButton("=",this)
    
      //设置默认属性为禁用
    
      m_btnCalc->setEnanled(false);
    
     
    
      //创建水平布局器,将所有的组件从左至右添加到布局器中,它将自动调节每个组件的大小和位置
    
      QHBoxLayout* layout =new QHBoxLayout(this);
    
      //为水平布局器添加组件
    
      layout->addWidget(m_editX);//左操作数
    
      layout->addWidget(new QLabel('+'));//加号
    
      layout->addWidget(m_editY);//右操作数
    
      layout->addWidget(m_btnCalc);//等号
    
      layout->addWidget(m_editZ);//结果(只读)
    
      //设置启用布局器
    
      setLayout(layout);
    
     
    
      //QLineEdit组件中输入时,将发送信号:textChanged
    
      connect(m_editX,SIGNAL(textChanged(const string&)),this,SLOT(enableCalcButton()));
    
      connect(m_editX,SIGNAL(textChanged(const string&)),this,SLOT(enableCalcButton()));
    
      
    
      //点击=号按钮发送clicked信号
    
      connect(m_btnCalc,SIGNAL(clicked()),this,SLOT(calcClicked()));
    
    }
    
     
    
    //使能等号按钮的槽函数
    
    void CalculatorDialog::enableCalcButton(void){
    
       //检查左右操作数是否为有效数字
    
      bool bXOk;
    
      bool bYOk;
    
      
    
      //text():获取QLineEdit输入的数据,返回值是QString类型
    
      //toDouble():将QString类型转换成double类型,参数是值结果参数,表示转换是否成功
    
      m_editX->text().toDouble(&bXOk);
    
      m_editX->text().toDouble(&bXOk);
    
     
    
      //设置=号按钮
    
      m_btnCalc->setEnabled(bXOk&&bYOk);
    
    }
    
     
    
    //计算结果的槽函数
    
    void CalculatorDialog::calcClicked(void){
    
      //转换为double并计算
    
       double res=m_editX->text().toDouble()+m_editY->text().toDouble();
    
     
    
      //将double转换为字符串文本
    
      QString str=QString::number(res,'g',15);
    
     
    
      //显示文本
    
      m_editZ->serText(str);
    
    }
    //Calculator.cpp主函数文件
    
     
    
    #include<QApplication>
    #include"CalculatorDialog.h"
    
    
    int main(int argc,char** argv){
      QApplication app(argc,argv);
      
      CalculatorDialog calc;
      calc.show()
      
      return app.exec();
    }
    
    










  • 相关阅读:
    docker学习笔记3:镜像操作(查找和下载)
    docker学习笔记2:容器操作
    docker学习笔记1:docke环境的查看
    CSS鼠标样式
    Ubuntu下安装和配置mysql
    HR函数学习01——创建组织单位
    SAP模块常用增强总结{转载}
    SAP物料批次管理配置及操作手册(轉載)
    交货单开票
    ABAP之PINYING拼音
  • 原文地址:https://www.cnblogs.com/ptfe/p/11312841.html
Copyright © 2020-2023  润新知