QT学习笔记

这里写目录标题

第0课 - 开发环境搭建

第1课 - GUI 程序原理分析

第2课 - GUI 程序实例分析

在这里插入图片描述
增加点击X,退出程序的功能

static HWND MainWindow = NULL; // 主窗口句柄标  移动位置
void App_Exit()
{
	PostQuitMessage(0);
}

void Button_handler(int i,int e)
{
	if((i==BUTTON_ID)&& (e==BN_CLICKED))
	{
		MessageBox(MainWindow,L"My button is clicked",L"Click message",0);

	}
	

}

//static HWND MainWindow = NULL; // 主窗口句柄标 移动到上面
.......

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	if(message==WM_DESTROY)
	{
		//PostQuitMessage(0);
		App_Exit();//
	}

	if(message==WM_COMMAND)
	{
		
		Button_handler(LOWORD(wParam),HIWORD(wParam));//获取id值
	}
    /* 调用系统提供的默认消息处理函数 */
    return DefWindowProc(hWnd, message, wParam, lParam);
}

MFC应用程序创建
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

void CMFCdemoDlg::OnClickedMyButton1()
{
	// TODO: 在此添加控件通知处理程序代码
	MessageBox(L"my button is clicked");
}

在字符串前加一个L作用: unicode字符集是两个字节组成的。L告示编译器使用两个字节的 unicode 字符集。
如 L"我的字符串" 表示将ANSI字符串转换成unicode的字符串,就是每个字符占用两个字节。

第3课 - QT 的诞生和本质

上一课的代码使用的是面向过程的方法,所以只有一个文件
在这里插入图片描述

这节课是面向对象的方法,多个cpp文件
在这里插入图片描述
在这里插入图片描述

#pragma once//??啥意思来着 这个文件只能编译一次

#include <windows.h>

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

第4课 - Hello QT

在这里插入图片描述
条件断点

第5课 - Qt Creator工程介绍

第6课 - 窗口部件及窗口类型

在这里插入图片描述

#include <QLabel>
//#include <QtGui>//qlabel 版本不一样 
#include "Widget.h"
#include <QApplication>


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
   // QWidget w;//Widget w;
   // QWidget w(NULL,Qt::Dialog);
    //QWidget w(NULL,Qt::Window);
   // QWidget w(NULL,Qt::SplashScreen);

    //QWidget w(NULL,Qt::Window|Qt::WindowStaysOnTopHint);
    QWidget w(NULL,Qt::Window|Qt::WindowStaysOnTopHint|Qt::WindowContextHelpButtonHint);
QLabel l(&w);
l.setText("this is a label");

    w.setWindowTitle("title");
    w.show();/**/

/*label也可以是窗体
QLabel l;
l.setText("this is a label");

    l.setWindowTitle("title");
    l.show();*/

    return a.exec();
}

第7课 - Qt 中的坐标系统

在这里插入图片描述
在这里插入图片描述

第8课 - 启航!第一个应用实例

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private:
    Ui::Widget *ui;
};

#endif // WIDGET_H


#include "widget.h"
#include "ui_widget.h"

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

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

在这里插入图片描述
在这里插入图片描述

//#include "widget.h"
#include <QApplication>
#include<QWidget>
#include<QLineEdit>
#include<QPushButton>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //Widget w;
    QWidget *w=new QWidget(NULL,Qt::WindowCloseButtonHint);//窗口最大化优化 WindowMaximizeButtonHint

    QLineEdit *e=new QLineEdit(w);
    e->setReadOnly(true);
    e->resize(240,30);
    e->move(10,10);
    QPushButton* button[20]={0};
    const char* texts[20]={
        "7","8","9","+","(",
        "4","5","6","-",")",
        "1","2","3","*","<-",
        "0",".","=","/","C",
    };
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<5;j++)
        {
            button[i*5+j]=new QPushButton(w);
            button[i*5+j]->resize(40,40);
            button[i*5+j]->move(10+(10+40)*j,50+(10+40)*i);
            button[i*5+j]->setText(texts[i*5+j]);

        }
    }

    int ret=0;
    //w.show();
    w->show();
    w->setFixedSize(w->width(),w->height());//放在show后面

    //return a.exec();
    ret=a.exec();
    delete w;


    return ret;


}

第9课 - 计算器界面代码重构

#include "calculatorui.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //Widget w;
    /*
    QWidget *w=new QWidget(NULL,Qt::WindowCloseButtonHint);//窗口最大化优化 WindowMaximizeButtonHint

    QLineEdit *e=new QLineEdit(w);
    e->setReadOnly(true);
    e->resize(240,30);
    e->move(10,10);
    QPushButton* button[20]={0};
    const char* texts[20]={
        "7","8","9","+","(",
        "4","5","6","-",")",
        "1","2","3","*","<-",
        "0",".","=","/","C",
    };
    for(int i=0;i<4;i++)
    {
        for(int j=0;j<5;j++)
        {
            button[i*5+j]=new QPushButton(w);
            button[i*5+j]->resize(40,40);
            button[i*5+j]->move(10+(10+40)*j,50+(10+40)*i);
            button[i*5+j]->setText(texts[i*5+j]);

        }
    }
*/
    CalculatorUI * c1=CalculatorUI::newInstance();

    int ret=-1;
    if(c1!=NULL)
    {
        c1->show();
        ret=a.exec();
        delete c1;
    }

    //w.show();
    /*
    w->show();
    w->setFixedSize(w->width(),w->height());//放在show后面
*/
    //return a.exec();

    //delete w;


    return ret;


}

#ifndef _CALCULATORUI_H
#define _CALCULATORUI_H
#include <QApplication>
#include<QWidget>
#include<QLineEdit>
#include<QPushButton>

class CalculatorUI:public QWidget
{
private:
    QLineEdit *m_e;
    QPushButton* m_button[20];
    CalculatorUI();
    bool construct();
public:
    static CalculatorUI* newInstance();
    void show();
    ~CalculatorUI();


};

#endif // CALCULATORUI_H
#include "calculatorui.h"

CalculatorUI::CalculatorUI():QWidget(NULL,Qt::WindowCloseButtonHint)
{
    //非系统变量

}
bool CalculatorUI::construct()
{
    bool ret=true;
    const char* texts[20]={
        "7","8","9","+","(",
        "4","5","6","-",")",
        "1","2","3","*","<-",
        "0",".","=","/","C",
    };

    m_e=new QLineEdit(this);
    if(m_e!=NULL)
    {
        m_e->setReadOnly(true);
        m_e->resize(240,30);
        m_e->move(10,10);
        //ret=true;

    }
    else
    {
        ret=false;
    }



    for(int i=0;(i<4)&&ret;i++)//&&ret
    {
        for(int j=0;(j<5)&&ret;j++)
        {
            m_button[i*5+j]=new QPushButton(this);
            if(m_button[i*5+j]!=NULL)
            {
                m_button[i*5+j]->resize(40,40);
                m_button[i*5+j]->move(10+(10+40)*j,50+(10+40)*i);
                m_button[i*5+j]->setText(texts[i*5+j]);
               // ret=true;

            }
            else
            {
                ret=false;
            }


        }
    }
    return ret;


}

CalculatorUI* CalculatorUI::newInstance()
{
    CalculatorUI* ret=new CalculatorUI();
    if((ret==NULL)||ret->construct()==false)//CalculatorUI::construct()==false
    {
        delete ret;
        ret=NULL;
    }

    return ret;

}
void CalculatorUI::show()//CalculatorUI* obj
{
    QWidget::show();//obj->  QWidget::   CalculatorUI::XXX 死循环??
    setFixedSize(width(),height());
}

CalculatorUI::~CalculatorUI()
{
    delete(m_e);
    for(int i=0;i<20;i++)
    {
        delete(m_button[i]);
    }


}

第10课 - 初探 Qt 中的消息处理

信号(signal):操作系统发送的消息
槽(slot):消息处理函数
连接():利用connect方法(发送对象,消息名,接收对象,接受对象的成员函数)

槽的 必须在类声明加上Q_OBJECT
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第11课 - Qt 中的字符串类

在这里插入图片描述


#include <QDebug>

void Sample_1()
{
    QString s = "add";

    s.append(" ");    // "add "
    s.append("Qt");   // "add Qt"
    s.prepend(" ");   // " add Qt"
    s.prepend("C++"); // "C++ add Qt"

    qDebug() << s;

    s.replace("add", "&"); // "C++ & Qt"

    qDebug() << s;
}

void Sample_2()
{
    QString s = "";
    int index = 0;

    s.sprintf("%d. I'm %s, thank you!", 1, "Delphi Tang"); // "1. I'm Delphi Tang, thank you!"

    qDebug() << s;

    index = s.indexOf(",");

    s = s.mid(0, index);   // "1. I'm Delphi Tang"

    qDebug() << s;

    index = s.indexOf(".");

    s = s.mid(index + 1, s.length()); // " I'm Delphi Tang"
    s = s.trimmed();                  // "I'm Delphi Tang"

    qDebug() << s;

    index = s.indexOf(" ");

    s = s.mid(index + 1, s.length()); // "Delphi Tang"

    qDebug() << s;
}

void Sample_3(QString* a, int len)
{
    for(int i=0; i<len; i++)
    {
        for(int j=i+1; j<len; j++)
        {
            if( a[j] < a[i] )
            {
                QString tmp = a[i];
                a[i] = a[j];
                a[j] = tmp;
            }
        }
    }
}

int main()
{
    qDebug() << "Sample_1:";

    Sample_1();

    qDebug() << endl;
    qDebug() << "Sample_2:";

    Sample_2();

    qDebug() << endl;
    qDebug() << "Sample_3:";

    QString company[5] =
    {
        QString("Oracle"),
        QString("Borland"),
        QString("Microsoft"),
        QString("IBM"),
        QString("D.T.Software")
    };

    Sample_3(company, 5);

    for(int i=0; i<5; i++)
    {
        qDebug() << company[i];
    }

    return 0;
}

在这里插入图片描述

第12课 - 计算器核心解析算法(上)

第13课 - 计算器核心解析算法(中)

遇到问题
“+9.11”
“+”
“-”
“3”
“-”
“1”
“*”
“-”
“5” 应该是-5

QQueue<QString> CalculatorDec::split(const QString& exp)// 日期:8/28
 {
     QQueue<QString> ret;
     QString num="";
     QString pre="";

     for(int i=0;i<exp.length();i++)
     {
         if(isDigitorDot(exp[i]))//数字和点
         {
             num+=exp[i];  //QString  Qchar
             pre=exp[i];
         }
         else if(isSymbol(exp[i]))//加减乘除括号  isOperator    QString转换为Qchar类型XXX  本来就是Qchar
         {
             if(!num.isEmpty())//有内容,数值丢到队列去   num!=""!num.isEmpty()
             {
                 ret.enqueue(num);
                 num.clear();//="";
             }
             if(isSign(exp[i]) &&((pre=="")||isOperator(pre)||("("==pre)))//当前是否是正负号(首位,前面是加减乘除,前面是括号)  isSign(exp[i]) &&    duole ||isRight(pre)
             {
                 num+=exp[i];//

             }
             else
             {
                 ret.enqueue(exp[i]);

             }
             pre=exp[i];

         }
         //pre=exp[i];不能放这里
     }
     if( !num.isEmpty() )//防止最后一位数值漏了
     {
             ret.enqueue(num);
    }
/*
     for(int i=0; i<exp.length(); i++)
        {
            if( isDigitorDot(exp[i]) )
            {
                num += exp[i];
                pre = exp[i];
            }
            else if( isSymbol(exp[i]) )
            {
                if( !num.isEmpty() )
                {
                    ret.enqueue(num);

                    num.clear();
                }

                if( isSign(exp[i]) && ((pre == "") || (pre == "(") || isOperator(pre)) )
                {
                    num += exp[i];
                }
                else
                {
                    ret.enqueue(exp[i]);
                }

                pre = exp[i];
            }
        }

        if( !num.isEmpty() )
        {
            ret.enqueue(num);
        }
*/
     return ret;

 }

在这里插入图片描述
在这里插入图片描述

 bool CalculatorDec::transform(QQueue<QString>& exp, QQueue<QString>& output)//中缀转后缀 (借助栈删除括号)
 {
     bool ret=match(exp);//false;遗漏 调用匹配函数
     output.clear();//漏了
     QStack<QString> stack;

        //output.clear();

        while( ret && !exp.isEmpty() )
        {
            QString e=exp.dequeue();//从队列取出元素
            if(isNumber(e))//是数字入队列
            {
                output.enqueue(e);
            }//
            else if(isOperator(e))//符号,当优先级低于或等于栈顶元素,先入队列再出栈,  最后把符号入栈
            {
                while( !stack.isEmpty() &&(priority(e)<=priority(stack.top())))// !stack.isEmpty() && 漏了
                {
                    output.enqueue(stack.top());
                    stack.pop();
                }
                stack.push(e);

            }
            else if(isLeft(e))//左括号,入栈
            {
                stack.push(e);

            }
            else if(isRight(e))//右括号,当栈顶不是左括号,入队列在出栈,最后弹出左括号
            {
                    while( !stack.isEmpty() &&(!isLeft(stack.top())))//!stack.isEmpty() && 漏了,,,,!漏了
                    {
                        output.enqueue(stack.top());
                        stack.pop();
                    }
                    if( !stack.isEmpty())//漏了判断
                    {
                        stack.pop();
                    }

            }
            else
            {
                ret=false;//都不是的话,失败
            }
        }
        while( !stack.isEmpty() )//遗漏,栈里遗漏的入队列
           {
               output.enqueue(stack.pop());
           }

           if( !ret )//遗漏,半成品晴空
           {
               output.clear();
           }

        return ret;

 }

第14课 - 计算器核心解析算法(下)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 QString CalculatorDec::calculate(QString l,QString r,QString op)//运算2个数
 {
     QString ret="error";
     if(isNumber(l)&&isNumber(r)&&isOperator(op))
     {
         double a=l.toDouble();
         double b=r.toDouble();
         if(op=="+")
         {
             ret.sprintf("%f",a+b);
         }
         else if(op=="-")
         {
             ret.sprintf("%f",a-b);
         }
         else if(op=="*")
         {
             ret.sprintf("%f",a*b);
         }
         else if(op=="/")
         {
             const double P = 0.000000000000001;

             if( (-P < b) && (b < P) )
             {
                 ret = "Error";
             }
             else
             {
                 ret.sprintf("%f",a/b);
             }

         }
         else
         {
             ret="error";
         }

     }
     return ret;

 }
 QString CalculatorDec::calculate(QQueue<QString>& exp)//处理后缀表达式
 {
     QString ret="error";
     QStack<QString> stack;
     while(!exp.isEmpty())
     {
         QString e=exp.dequeue();
         if(isNumber(e))
         {
             stack.push(e);
         }
         else if( isOperator(e)  )//是运算符,就弹出右操作数,左操作数,计算后入栈
         {
             QString r=!stack.isEmpty()?stack.pop():"";

             QString l=!stack.isEmpty()?stack.pop():"";
             QString resu=calculate(l,r,e);
             if(resu!="error")
             stack.push(resu);
             else
             {
                 break;
             }
         }
         else
         {
             //ret="error";
             break;
         }
     }
     if(exp.isEmpty()&&stack.length()==1&&isNumber(stack.top()))//漏了判断
     {
        ret=stack.pop();
     }
     return ret;
 }

构造函数的测试封装成函数

CalculatorDec::CalculatorDec()
{
    m_exp="";
    m_result="";
    QQueue<QString> r = split("+9.11 + ( -3 - 1 ) * -5 ");//"+9.11 + ( -3 - 1 ) * -5 "  "+9.11 + 5 "

       for(int i=0; i<r.length(); i++)
       {
           qDebug() << r[i];
       }
       qDebug()<< match(r);
       QQueue<QString> r1;
       qDebug()<<"transform:"<<transform(r,r1);
       for(int i=0; i<r1.length(); i++)
       {
           qDebug() << r1[i];
       }

       QString res=calculate(r1);
       qDebug()<<"res:"<<res<<endl;



}


 bool CalculatorDec::expression(const QString& exp)
 {
     bool ret=true;
     QQueue<QString> splexp = split(exp);//"+9.11 + ( -3 - 1 ) * -5 "  "+9.11 + 5 "
     m_exp=exp;
     QQueue<QString> r1;//后缀表达式
    
    if(transform(splexp,r1))
    {
        
        m_result=calculate(r1);
        ret=(m_result!="error");
    }
    else
    {
        ret=false;
        m_result="error";
    }
    return ret;    
 }

主程序的代码

CalculatorDec d;
    d.expression("+3 + ( 3 - 4 ) * 2");
    qDebug()<<"res:"<<d.result();

第15课 - 用户界面与业务逻辑的分离

在这里插入图片描述
1添加头文件icalculator 定义接口

#ifndef _ICALCULATOR_H_
#define _ICALCULATOR_H_
#include<QString>
class icalculator
{
public:
    virtual bool expression(const QString& exp)=0;//接收输入的四则运算表达式
    virtual QString result() = 0; 
    
};

#endif // ICALCULATOR_H

2,实现qcalculator

#ifndef _QCALCULATOR_H_
#define _QCALCULATOR_H_
#include"calculatorui.h"
#include"CalculatorDec.h"

class Qcalculator
{
protected:
    CalculatorUI* m_ui;//二阶构造的,所以 指针
    CalculatorDec m_cal;
    Qcalculator();
    bool construct();
public:
    static Qcalculator* Newinstance();
    void show();
    ~Qcalculator();
};

#endif // QCALCULATOR_H
#include "Qcalculator.h"

Qcalculator::Qcalculator()
{

}

bool Qcalculator::construct()
{
    m_ui=CalculatorUI::newInstance();
    
    return (m_ui!=NULL);
    
}

Qcalculator* Qcalculator::Newinstance()
{
    Qcalculator* ret=new Qcalculator();
    if(ret==NULL||ret->construct()==false)
    {
       // delete ret->m_ui;
        delete ret;
        ret=NULL;
    }
    
    return ret;
    
}

void Qcalculator::show()
{
    m_ui->show();//m_ui->
}

Qcalculator::~Qcalculator()
{
    delete m_ui;
    
}

3,QcalculatorUI依赖接口的实现

4,calculatorDec关联接口 继承的方式

5.qcalculator 的construct函数的实现

第16课 - Qt 对象间的父子关系

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

#include <QCoreApplication>
#include<QDebug>
void fctest()
{
    QObject* p=new QObject();
    QObject* c1=new QObject();
    QObject* c2=new QObject();
    c1->setParent(p);
    c2->setParent(p);
    qDebug()<<"c1:"<<c1;
    qDebug()<<"c2:"<<c2;
    const QObjectList & list=p->children();
    for(int i=0;i<list.length();i++)
    {
        qDebug()<<list[i];
    }
    qDebug()<<"p:"<<p;
    qDebug()<<"c1->parent():"<<c1->parent();
    qDebug()<<"c2->parent():"<<c2->parent();
}
class Mobj:public QObject
{
    QString m_name;
public:
    Mobj(const QString& name)
    {
        m_name=name;
        qDebug()<<"constructor:"<<m_name;
    }
    ~Mobj()
    {
        qDebug()<<"deconstructor:"<<m_name;
    }
};
void deltest()
{
    Mobj* o1=new Mobj("o1");
    Mobj* o2=new Mobj("o2");
    Mobj* o3=new Mobj("o3");
    Mobj* o4=new Mobj("o4");
    o2->setParent(o1);
    o3->setParent(o1);
    o4->setParent(o3);
   delete o3;
    qDebug()<<"o2:"<<o2;
    const QObjectList & list=o1->children();
    for(int i=0;i<list.length();i++)
    {
        qDebug()<<"o1->children():       "<<list[i];
    }
    //delete o4;//pure virtual method called
   // terminate called without an active exception
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    //fctest();
    deltest();
    return a.exec();
}

第17课 - 对话框及其类型

#include <QWidget>
#include<QDialog>
#include <QApplication>
#include "dialog.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);//实验1:wi作da的父对象,2个
    QWidget wi;//父类
    QDialog da(&wi);//子类
    //da.resize(2000,1500);
    //实验2:wi嵌入到da,看上去就一个窗体
    QDialog da;//子类
    QWidget wi(&da);//父类
    

     //wi.resize(1000,1000);
   da.show();
    da.setWindowTitle("i am Qdialog");
    wi.show();
    wi.setWindowTitle("i am Qwidget");

    return a.exec();
}

一个是模态对话框(model dialog box),一个是非模态对话框(modeless dialog box)

在这里插入图片描述
在这里插入图片描述
GUI程序运行第一个出现的窗体,叫主窗体

void Dialog::ModalBtn_Clicked()
{
    qDebug()<<"ModalBtn_Clicked begin";
    QDialog d;//模态对话框,没定义父组件,效果一样(this)
    d.exec();//阻塞了
    qDebug()<<"ModalBtn_Clicked end";//关闭后才执行

}
void Dialog::NormalBtn_Clicked()
{
    qDebug()<<"NormalBtn_Clicked begin";
    //QDialog d;//非模态对话框  局部变量.一闪就没了
    //d.show();
   // QDialog* d=new QDialog();//堆,没定义父组件,未处于窗体顶层;
    //d->show();//没有阻塞了 一闪就没了,在堆上搞
    QDialog* d=new QDialog(this);//堆,没定义父组件,未处于窗体顶层;
    d->show();//没有阻塞了 一闪就没了,在堆上搞
    qDebug()<<"NormalBtn_Clicked end";
}

混合模式的对话框

void Dialog::MixedBtn_Clicked()
{
    qDebug()<<"MixedBtn_Clicked begin";
    QDialog* d=new QDialog(this);

    d->setAttribute(Qt::WA_DeleteOnClose);
    d->setModal(this);
    d->show();
    qDebug()<<"MixedBtn_Clicked end";//打开会运行到这里,但无法点击主窗体
}

模态对话框的返回值

void Dialog::ModalBtn_Clicked()
{
    qDebug()<<"ModalBtn_Clicked begin";
    done(Accepted);
    qDebug()<<"ModalBtn_Clicked end";//关闭后才执行

}
void Dialog::NormalBtn_Clicked()
{
    qDebug()<<"NormalBtn_Clicked begin";
    done(Rejected);
    qDebug()<<"NormalBtn_Clicked end";
}
void Dialog::MixedBtn_Clicked()
{
    qDebug()<<"MixedBtn_Clicked begin";
    done(100);
    qDebug()<<"MixedBtn_Clicked end";
}

#include "dialog.h"
#include <QApplication>
#include<QDebug>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog d;
    int r=d.exec();

    if(r==QDialog::Accepted)
    {
        qDebug()<<"Accepted";

    }
    else if(r==QDialog::Rejected)
    {
        qDebug()<<"Rejected";

    }
    else
    {
        qDebug()<<r;

    }

    //return a.exec();//进入了2次消息循环,窗体没了,程序还在
    return r;
}

第18课 - 登录对话框实例分析

在这里插入图片描述
在这里插入图片描述

#include "QLoginDialog.h"
#include<QDebug>
QLoginDialog::QLoginDialog(QWidget* parent):QDialog(parent,Qt::WindowCloseButtonHint),UserLabel(this),
    PwdLabel(this),UserEdit(this),PwdEdit(this),LoginBtn(this),CancelBtn(this)
{
    UserLabel.setText("User ID:");
    UserLabel.move(20,30);
    UserLabel.resize(60,25);

    UserEdit.move(85,30);
    UserEdit.resize(180,25);

    PwdLabel.setText("Password:");
    PwdLabel.move(20,65);
    PwdLabel.resize(60,25);
    PwdEdit.setEchoMode(QLineEdit::Password);//2秘密隐藏

    PwdEdit.move(85,65);
    PwdEdit.resize(180,25);

    LoginBtn.setText("Login");
    LoginBtn.move(180,110);
    LoginBtn.resize(85,25);



    CancelBtn.setText("Cancel");
    CancelBtn.move(85,110);
    CancelBtn.resize(85,25);

    setWindowTitle("Login");

    setFixedSize(285,170);//2固定大小
    //


    QObject::connect(&LoginBtn,SIGNAL(clicked()),this,SLOT(LoginBtn_Clicked()));
    QObject::connect(&CancelBtn,SIGNAL(clicked()),this,SLOT(CancelBtn_Clicked()));

}

void QLoginDialog::LoginBtn_Clicked()
{
    qDebug()<<"LoginBtn_Clicked begin";

    m_user=UserEdit.text().trimmed();//去掉前后空格
    m_pwd=PwdEdit.text();
    done(Accepted);//3 点击后关闭窗体
    qDebug()<<"LoginBtn_Clicked end";
}
void QLoginDialog::CancelBtn_Clicked()
{
    qDebug()<<"CancelBtn_Clicked begin";
    done(Rejected);//3
    qDebug()<<"CancelBtn_Clicked end";

}

QString QLoginDialog::getUser()
{
    return m_user;
}
QString QLoginDialog::getPwd()
{
    return m_pwd;
}
QLoginDialog::~QLoginDialog()//loule
{

}

#include "widget.h"
#include "QLoginDialog.h"
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent),TestBtn(this)
{
    TestBtn.setText("Test Login Dialog");
    setFixedSize(200,50);
    QObject::connect(&TestBtn,SIGNAL(clicked()),this,SLOT(TestBtn_Clicked()));
}
void Widget::TestBtn_Clicked()
{
    QLoginDialog dlg;
    // dlg.exec();//改掉
    if(dlg.exec()==QDialog::Accepted)
    {
        //qDebug()<<"Login";
        //qDebug()<<"user:"<<dlg.getUser()<<",password:"<<dlg.getPwd();
        qDebug()<<"user:"+dlg.getUser();//公有成员函数返回
        qDebug()<<"password:"+dlg.getPwd();//发送到服务器验证
    }//如何获取用户名和秘码  1,先判断名或密码空,提示错误,   2, 随机验证码
    else
    {
    }
   
}
Widget::~Widget()
{

}

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

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

    return a.exec();
}


在这里插入图片描述
LoginBtn_Clicked begin
LoginBtn_Clicked end
Login
“user:dfgsg”
“password:111111111111”
在这里插入图片描述

第19课 - Qt 中的标准对话框(上)

标准对话框(继承自QDialog类)
QMessagebox
QFileDialog
QPrintDialog
QColourDialog
QInputDialog
QProgessDialog
3板斧//定义对象,设置属性,判断(exec)获取数据,处理数据
QMessagebox,关程序,提示要不要保存
设置属性set windowtitle Text Icon StandardButtons
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

void Widget::SimMsgBtn_Clicked()
{
    QMessageBox msg(this);
    msg.setText("this is a message dialog!!");
    msg.exec();

}
void Widget::CusMsgBtn_Clicked()
{
    /*
    QMessageBox msg(this);

    msg.setWindowTitle("Title");
    msg.setText("this is a detail message dialog!!");
    msg.setIcon(QMessageBox::Information);
    msg.setStandardButtons(QMessageBox::Ok|QMessageBox::Cancel|QMessageBox::YesToAll);
    */
    //代替上面5行的函数
    QMessageBox msg;
    msg.about(this,"about title","about this is a detail message dialog!!");
    //msg.critical(this,"critical title","critical this is a detail message dialog!!");
    //msg.information(this,"info title","info this is a detail message dialog!!");
    //msg.warning(this,"warning title","warning this is a detail message dialog!!");
    //msg.question(this,"question title","question this is a detail message dialog!!");
    if(msg.exec()==QMessageBox::Ok)
    {
        qDebug() << "ok button";
    }
    //msg.exec();

}
void Widget::OpenFileBtn_Clicked()
{
    /*

    QFileDialog dlg(this);
    dlg.setAcceptMode(QFileDialog::AcceptOpen);//打开模式
    //dlg.setFilter("Text(*.txt)");
     dlg.setNameFilter("Text(*.txt)");// //过滤
    dlg.setFileMode(QFileDialog::ExistingFiles);//1   ExistingFile  多

    if(dlg.exec()==QFileDialog::Accepted)
    {
        QStringList fs=dlg.selectedFiles();
        for(int i=0; i<fs.count();i++)
        {
            qDebug()<< fs[i];
        }
    }//但是没有文件类型过滤
    //文件类型过滤器
    */
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),//tr()Returns a translated version of sourceText, 
                                                    //optionally based on a disambiguation string and value of n for strings 
                                                    //containing plurals; otherwise returns QString::fromUtf8(sourceText) 
                                                    //if no appropriate translated string is available.
                                                    "",//""没记录    "/home"硬盘根目录
                                                     tr("Images (*.png *.xpm *.jpg)"));
    qDebug()<<fileName;
    //getOpenFlieName   省略了好多行
    //getOpernFileNames
    //getSaveFileName怎么用??

}
void Widget::SaveFileBtn_Clicked()
{
    QFileDialog dlg(this);
    dlg.setAcceptMode(QFileDialog::AcceptSave);//保存模式
    //dlg.setFilter("Text(*.txt)");
     dlg.setNameFilter("Text(*.txt)");//*.txt//过滤
   // dlg.setFileMode(QFileDialog::ExistingFiles);//1   ExistingFile  多

    if(dlg.exec()==QFileDialog::Accepted)
    {
        QStringList fs=dlg.selectedFiles();
        for(int i=0; i<fs.count();i++)
        {
            qDebug()<< fs[i];
        }
    }//但是没有文件类型过滤

}

在这里插入图片描述

第20课 - Qt 中的标准对话框(中)

颜色对话框
RGB HSV(色调,饱和度,明度) CMYK
QColour
在这里插入图片描述
透明度 和RGB

输入 文本 整数 浮点数

void Widget::ColourDialogBtn_Clicked()
{
    QColorDialog dlg(this);
    dlg.setWindowTitle("color title");
    //dlg.setCurrentColor(Qt::blue);
    dlg.setCurrentColor(QColor(100,111,222));

    if(dlg.exec()==QColorDialog::Accepted)
    {
        qDebug()<<dlg.selectedColor();

        QColor color=dlg.selectedColor();
        qDebug()<<color;
        qDebug()<<color.red();
        qDebug()<<color.green();
        qDebug()<<color.blue();
        qDebug()<<color.hue();
        qDebug()<<color.saturation();
        qDebug()<<color.value();

    }
//getColor??
}
void Widget::InputDialogBtn_Clicked()
{
    QInputDialog dlg(this);
    dlg.setWindowTitle("input Test title");
    dlg.setLabelText("Please input an integer:");
//    dlg.setInputMode(QInputDialog::IntInput);//数字
//    dlg.setIntMinimum(0);
//    dlg.setIntMaximum(255);

     dlg.setInputMode(QInputDialog::TextInput);

    if(dlg.exec()==QInputDialog::Accepted)
    {
//        qDebug()<<dlg.intValue();
          qDebug()<<dlg.textValue();
    }
    //getDouble getInt  getItem getText??使用
}

第21课 - Qt 中的标准对话框(下)

字体对话框

QFont类
报错

E:\qtFile\build-QT21QFontDialogTest-Desktop_Qt_5_9_4_MinGW_32bit-Debug\debug\widget.o:-1: In function `ZN6Widget22PrintDialogBtn_ClickedEv':
E:\qtFile\QT21QFontDialogTest\widget.cpp:62: error: undefined reference to `_imp___ZN12QPrintDialogC1EP7QWidget'
E:\qtFile\QT21QFontDialogTest\widget.cpp:62: error: undefined reference to `_imp___ZN12QPrintDialogD1Ev'

collect2.exe:-1: error: error: ld returned 1 exit status

参考帮助文档
在这里插入图片描述

pro文件添加一行
QT += printsupport #添加QPrintDialog

在这里插入图片描述

void Widget::PrintDialogBtn_Clicked()
{
    QPrintDialog dlg(this);
   dlg.setWindowTitle("print dialog");

   if(dlg.exec()==QPrintDialog::Accepted)
   {
       QPrinter* p=dlg.printer();//打印参数
       QTextDocument td;//被打印的文件
       //td.setPlainText("printer object test!!");
       td.setHtml("<h1>qt html object print</h1>");
       p->setOutputFileName("E:\\qttest.pdf");//打印的这个文件上
//       p->setOutputFileName("E:\\qttest.xps");//没有这个打印机,
       td.print(p);


   }

第22课 - 布局管理器(一)

绝对定位
在这里插入图片描述
高度没变

void Widget::vboxlayout()
{
    QVBoxLayout* layout=new QVBoxLayout();

    Btn1.setText("button1");
    Btn1.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//高度拉伸
    Btn1.setMinimumSize(160,30);
    Btn2.setText("button2");
    Btn2.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn2.setMinimumSize(160,30);
    Btn3.setText("button3");
    Btn3.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn3.setMinimumSize(160,30);
    Btn4.setText("button4");
    Btn4.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn4.setMinimumSize(160,30);
    layout->setSpacing(20);
    layout->addWidget(&Btn1);
    layout->addWidget(&Btn2);
    layout->addWidget(&Btn3);
    layout->addWidget(&Btn4);
    setLayout(layout);//
}

在这里插入图片描述

改写计算器程序,按钮变化

void Widget::vhboxlayout()
{
    QHBoxLayout* hlayout1=new QHBoxLayout();
    QHBoxLayout* hlayout2=new QHBoxLayout();
    QVBoxLayout* vlayout=new QVBoxLayout();

    Btn1.setText("button1");
    Btn1.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//高度拉伸
    Btn1.setMinimumSize(160,30);
    Btn2.setText("button2");
    Btn2.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn2.setMinimumSize(160,30);
    hlayout1->setSpacing(10);
    hlayout1->addWidget(&Btn1);
    hlayout1->addWidget(&Btn2);

    Btn3.setText("button3");
    Btn3.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn3.setMinimumSize(160,30);
    Btn4.setText("button4");
    Btn4.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn4.setMinimumSize(160,30);
    hlayout2->setSpacing(10);
    hlayout2->addWidget(&Btn3);
    hlayout2->addWidget(&Btn4);

    vlayout->setSpacing(20);
    vlayout->addLayout(hlayout1);
    vlayout->addLayout(hlayout2);
    setLayout(vlayout);//
}
void Widget::hboxlayout()
{
    QHBoxLayout* layout=new QHBoxLayout();

    Btn1.setText("button1");
    Btn1.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//高度拉伸
    Btn1.setMinimumSize(160,30);
    Btn2.setText("button2");
    Btn2.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn2.setMinimumSize(160,30);
    Btn3.setText("button3");
    Btn3.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn3.setMinimumSize(160,30);
    Btn4.setText("button4");
    Btn4.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn4.setMinimumSize(160,30);
    layout->setSpacing(20);
    layout->addWidget(&Btn1);
    layout->addWidget(&Btn2);
    layout->addWidget(&Btn3);
    layout->addWidget(&Btn4);
    setLayout(layout);//
}

在这里插入图片描述

第23课 - 布局管理器(二)

比例系数
setStretch
bool setStretchFactor(qwidget*,int)
bool setStretchFactor(qlayout*,int
在这里插入图片描述

void Widget::vhboxlayout()
{
    QHBoxLayout* hlayout1=new QHBoxLayout();
    QHBoxLayout* hlayout2=new QHBoxLayout();
    QVBoxLayout* vlayout=new QVBoxLayout();

    Btn1.setText("button1");
    Btn1.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//高度拉伸
    Btn1.setMinimumSize(160,30);
    Btn2.setText("button2");
    Btn2.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn2.setMinimumSize(160,30);
    hlayout1->setSpacing(10);
    hlayout1->addWidget(&Btn1);
    hlayout1->addWidget(&Btn2);

    Btn3.setText("button3");
    Btn3.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn3.setMinimumSize(160,30);
    Btn4.setText("button4");
    Btn4.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn4.setMinimumSize(160,30);
    hlayout2->setSpacing(10);
    hlayout2->addWidget(&Btn3);
    hlayout2->addWidget(&Btn4);

    vlayout->setSpacing(20);
    vlayout->addLayout(hlayout1);
    vlayout->addLayout(hlayout2);
    vlayout->setStretchFactor(hlayout1,1);//比例
    vlayout->setStretchFactor(hlayout2,3);
    setLayout(vlayout);//
}
void Widget::hboxlayout()
{
    QHBoxLayout* layout=new QHBoxLayout();

    Btn1.setText("button1");
    Btn1.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//高度拉伸
    Btn1.setMinimumSize(160,30);
    Btn2.setText("button2");
    Btn2.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn2.setMinimumSize(160,30);
    Btn3.setText("button3");
    Btn3.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn3.setMinimumSize(160,30);
    Btn4.setText("button4");
    Btn4.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn4.setMinimumSize(160,30);
    layout->setSpacing(20);
    layout->addWidget(&Btn1);
    layout->addWidget(&Btn2);
    layout->addWidget(&Btn3);
    layout->addWidget(&Btn4);
    layout->setStretchFactor(&Btn1,1);
    layout->setStretchFactor(&Btn2,2);
    layout->setStretchFactor(&Btn3,1);
    layout->setStretchFactor(&Btn4,2);
    setLayout(layout);//
}
void Widget::vboxlayout()
{
    QVBoxLayout* layout=new QVBoxLayout();

    Btn1.setText("button1");
    Btn1.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//高度拉伸
    Btn1.setMinimumSize(160,30);
    Btn2.setText("button2");
    Btn2.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn2.setMinimumSize(160,30);
    Btn3.setText("button3");
    Btn3.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn3.setMinimumSize(160,30);
    Btn4.setText("button4");
    Btn4.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    Btn4.setMinimumSize(160,30);
    layout->setSpacing(20);
    layout->addWidget(&Btn1);
    layout->addWidget(&Btn2);
    layout->addWidget(&Btn3);
    layout->addWidget(&Btn4);
    layout->setStretch(0,1);//0起始
    layout->setStretch(1,1);
    layout->setStretch(2,2);
    layout->setStretch(3,2);
    //一开始都一样的,后面逐渐满足比例,初始大小独立于布局管理器设置 不能保证始终保证满足比例
    setLayout(layout);//
}

在这里插入图片描述
嵌套布局管理器
QGridlayout嵌套qvboxlayout

第24课 - 布局管理器(三)

网格布局实现3行2列

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    QLabel* nameLbl = new QLabel("Name:");
    QLabel* mailLbl = new QLabel("Email:");
    QLabel* addrLbl = new QLabel("Address:");
    QLineEdit* nameEdit = new QLineEdit();
    QLineEdit* mailEdit = new QLineEdit();
    QLineEdit* addrEdit = new QLineEdit();
    QGridLayout* layout = new QGridLayout();

    layout->setSpacing(10);
    layout->addWidget(nameLbl, 0, 0);
    layout->addWidget(nameEdit, 0, 1);
    layout->addWidget(mailLbl, 1, 0);
    layout->addWidget(mailEdit, 1, 1);
    layout->addWidget(addrLbl, 2, 0);
    layout->addWidget(addrEdit,2, 1);
    layout->setColumnStretch(0, 1);
    layout->setColumnStretch(1, 4);

    setLayout(layout);
    setWindowTitle("FTP");
}

在这里插入图片描述

void setRowWrapPolicy(RowWrapPolicy policy)//行缠绕策略

在这里插入图片描述

void setLabelAlignment(Qt::Alignment alignment)//标签对其方式

第25课 - 布局管理器(四)

在这里插入图片描述在这里插入图片描述

void Widget::initcontrol()
{
    QStackedLayout* layout=new QStackedLayout();
    QHBoxLayout* hlayout=new QHBoxLayout();
    QWidget* widget=new QWidget();
    Btn1.setText("Test button 1");
    Btn2.setText("Test button 2");
    Btn3.setText("Test button 3");
    Btn4.setText("Test button 4");

    Btn2.setParent(widget);
    Btn3.setParent(widget);
    hlayout->addWidget(&Btn2);
    hlayout->addWidget(&Btn3);
    widget->setLayout(hlayout);

    layout->addWidget(&Btn1);
//    layout->addWidget(&Btn2);
//    layout->addWidget(&Btn3);
    layout->addWidget(widget);//间接实现嵌套
    layout->addWidget(&Btn4);
    layout->setCurrentIndex(1);
    setLayout(layout);


}

计时器
在这里插入图片描述

#include "widget.h"
#include<QStackedLayout>
#include<QHBoxLayout>
#include<QWidget>
#include<QDebug>
#include<QtCore>//qtimer
Widget::Widget(QWidget *parent)
    : QWidget(parent),Btn1(this),Btn2(this),Btn3(this),Btn4(this)
{
    initcontrol();


}
void Widget::initcontrol()
{
    QStackedLayout* layout=new QStackedLayout();
    QHBoxLayout* hlayout=new QHBoxLayout();
    QWidget* widget=new QWidget();
    QTimer* t=new QTimer(this);
    Btn1.setText("Test button 1");
    Btn2.setText("Test button 2");
    Btn3.setText("Test button 3");
    Btn4.setText("Test button 4");

    Btn2.setParent(widget);
    Btn3.setParent(widget);
    hlayout->addWidget(&Btn2);
    hlayout->addWidget(&Btn3);
    widget->setLayout(hlayout);

    layout->addWidget(&Btn1);
//    layout->addWidget(&Btn2);
//    layout->addWidget(&Btn3);
    layout->addWidget(widget);//间接实现嵌套
    layout->addWidget(&Btn4);
    layout->setCurrentIndex(1);
    setLayout(layout);
    connect(t,SIGNAL(timeout()),this,SLOT(timertimeout()));
    t->start(2000);
}

void Widget::timertimeout()
{
    qDebug()<<"time out";

}
Widget::~Widget()
{

}

#include "widget.h"
#include<QStackedLayout>
#include<QHBoxLayout>
#include<QWidget>
#include<QDebug>
#include<QtCore>//qtimer
Widget::Widget(QWidget *parent)
    : QWidget(parent),Btn1(this),Btn2(this),Btn3(this),Btn4(this)
{
    initcontrol();


}
void Widget::initcontrol()
{
    QStackedLayout* layout=new QStackedLayout();
    QHBoxLayout* hlayout=new QHBoxLayout();
    QWidget* widget=new QWidget();
    QTimer* t=new QTimer(this);
    Btn1.setText("Test button 1");
    Btn2.setText("Test button 2");
    Btn3.setText("Test button 3");
    Btn4.setText("Test button 4");

    Btn2.setParent(widget);
    Btn3.setParent(widget);
    hlayout->addWidget(&Btn2);
    hlayout->addWidget(&Btn3);
    widget->setLayout(hlayout);

    layout->addWidget(&Btn1);
//    layout->addWidget(&Btn2);
//    layout->addWidget(&Btn3);
    layout->addWidget(widget);//间接实现嵌套
    layout->addWidget(&Btn4);
    layout->setCurrentIndex(0);
    setLayout(layout);
    connect(t,SIGNAL(timeout()),this,SLOT(timertimeout()));
    t->start(2000);
}

void Widget::timertimeout()
{
    //qDebug()<<"time out";
    QStackedLayout* slayout=dynamic_cast<QStackedLayout*>(layout());//获取当前组件的布局管理器 ,返回Qlayout*
    if(slayout!=NULL)
    {
        int i=(slayout->currentIndex()+1)%slayout->count();
        slayout->setCurrentIndex(i);

    }

}
Widget::~Widget()
{

}

第26课 - 布局管理综合实例

第27课 - 应用程序中的主窗口

第28课 - 主窗口中的工具栏

第29课 - 主窗口中的状态栏

第30课 - Qt 中的文本编辑组件

第31课 - 软件开发流程简介

第32课 - Qt 中的文件操作

第33课 - 文本流和数据流

第34课 - 缓冲区操作与目录操作

第35课 - 文本编辑器中的数据存取

第36课 - 文本编辑器中的功能交互

第37课 - 深度解析 QMap 与 QHash

第38课 - Qt 中的事件处理(上)

第39课 - Qt 中的事件处理(下)

第40课 - 拖放事件深度剖析

第41课 - 编辑交互功能的实现

第42课 - 文本打印与光标定位

第43课 - 发送自定义事件(上)

第44课 - 发送自定义事件(下)

第45课 - 创建查找对话框

第46课 - 查找对话框的功能实现

第47课 - Qt 中的调色板

第48课 - 替换对话框的设计与实现

第49课 - 文本编辑器项目持续开发

第50课 - 关于对话框(About)

第51课 - 程序中的配置文件

第52课 - 命令行参数的应用

第53课 - 应用程序的打包与发布

第54课 - Qt 中的多页面切换组件

第55课 - 模型视图设计模式(上)

第56课 - 模型视图设计模式(中)

第57课 - 模型视图设计模式(下)

第58课 - 自定义模型类(上)

第59课 - 自定义模型类(中)

第60课 - 自定义模型类(下)

第61课 - 模型视图中的委托(上)

第62课 - 模型视图中的委托(下)

第63课 - 深入解析视图与委托(上)

第64课 - 深入解析视图与委托(下)

第65课 - 深入浅出信号与槽

第66课 - 基础图形绘制(上)

第67课 - 基础图形绘制(中)

第68课 - 基础图形绘制(下)

第69课 - 图像处理与绘制

第70课 - 文本绘制技巧

第71课 - 登录对话框的改进

第72课 - 进程与线程的概念

第73课 - Qt 中的多线程编程

第74课 - 多线程间的同步

第75课 - 多线程间的互斥(上)

第76课 - 多线程间的互斥(下)

第77课 - 银行家算法的分析与实现

第78课 - 多线程中的信号与槽(上)

第79课 - 多线程中的信号与槽(中)

第80课 - 多线程中的信号与槽(下)

第81课 - 信号与槽的连接方式

第82课 - 线程的生命期问题

第83课 - 另一种创建线程的方式

第84课 - 多线程与界面组件的通信(上)

第85课 - 多线程与界面组件的通信(下)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值