Qt学习笔记

论坛 期权论坛 脚本     
匿名技术用户   2021-1-2 22:26   77   0

Windows课亮闪闪整理:

namespace:

命名空间是ANSIC++引入的可以由用户命名的作用域,用来处理程序中 常见的同名冲突。

C语言中定义了3个层次的作用域,即文件(编译单元)、函数和复合语句。C++又引入了类作用域,类是出现在文件内的。在不同的作用域中可以定义相同名字的变量,互不于扰,系统能够区别它们。

命名空间:实际上就是一个由程序设计者命名的内存区域,程序设计者可以根据需要指定一些有名字的空间域,把一些全局实体分别放在各个命名空间中,从而与其他全局实体分隔开来.

为了解决C++标准库中的标识符与程序中的全局标识符之间以及不同库中的标识符之间的同名冲突,应该将不同库的标识符在不同的命名空间中定义(或声明)。标准C++库的所有的标识符都是在一个名为std的命名空间中定义的,或者说标准头文件(如iostream)中函数、类、对象和类模板是在命名空间 std中定义的。std是standard(标准)的缩写,表示这是存放标准库的有关内容的命名空间,含义请楚,不必死记。 这样,在程序中用到C++标准库时,需要使用std作为限定。如 std::cout<<”OK.”;

使用命名空间成员的方法

从上面的介绍可以知道,在引用命名空间成员时,要用命名空间名和作用域分辨符对命名空间成员进行限定,以区别不同的命名空间中的同名标识符。即:
命名空间名::命名空间成员名
这种方法是有效的,能保证所引用的实体有惟一的名字。但是如果命名空间名字比较长,尤其在有命名空间嵌套的情况下,为引用一个实体,需要写很长的名字。在一个程序中可能要多次引用命名空间成员,就会感到很不方便。
1 、使用命名空间别名
可以为命名空间起一个别名(namespace alias),用来代替较长的命名空间名。如
namespace Television //声明命名空间,名为Television
{ … }
可以用一个较短而易记的别名代替它。如:
namespace TV=Television//别名TV与原名Television等价
也可以说,别名TV指向原名Television,在原来出现Television的位置都可以无条件地用TV来代替。
2、使用using命名空间成员名
using后面的命名空间成员名必须是由命名空间限定的名字。例如:
using nsl::Student
以上语句声明:在本作用域(using语句所在的作用域)中会用到命名空间ns1中的成员Student,在本作用域中如果使用该命名空间成员时,不必再用命名空间限定。例如在用上面的using声明后,在其后程序中出现的Student就是隐含地指nsl::Student
using声明的有效范围是从using语句开始到using所在的作用域结束。如果在以上的using语句之后有以下语句:
Student studl(101,”Wang”,18)//此处的Student相当于ns1::Student
上面的语句相当于
nsl::Student studl(101”Wang”18)
又如
using nsl::fun//声明其后出现的fun是属于命名空间nsl中的fun


Example::Example()

//: m_iFirst(0)//去掉还是零

{

}

Example::Example(int iFirst)

// :m_iFirst(iFirst)//去掉变成0

{

}

int Example::getValue()

{

return m_iFirst;

}

Example::~Example(void)

{

}

void MyWidget::on_pButton_clicked()

{

ui->pButton->click();

QDialog *dialog = new QDialog(this);

dialog->show();

}

on_pButton_clicked()UI→pButton→clicked()陷入死循环,造成函数异常结束.

void MyWidget::on_pButton_clicked()

{

ui->pButton->close();

QDialog *dialog = new QDialog(this);

dialog->show();

}

运行关掉pButton,保留主窗口,开辟小窗口.

void MyWidget::on_pButton_clicked()

{

this->close();

QDialog *dialog = new QDialog(this);

dialog->show();

}

运行关掉主界面,开辟小窗口.

关闭界面即可以修改代码,也可以用ui修改,也可以俩个都改。

// 字体对话框

void MyWidget::on_pushButton_3_clicked()

{

// ok用于标记是否按下了“OK”按钮

bool ok;

QFont font = QFontDialog::getFont(&ok, this);

// 如果按下“OK”按钮,那么让字体对话框按钮使用新字体

// 如果按下“Cancel”按钮,那么输出信息

if (ok) ui->pushButton_3->setFont(font);

else qDebug() << tr("没有选择字体!");

}

按下ok后发现并没有效果,反而弹出了Gtk-Message: GtkDialog mapped without a transient parent. This is discouraged.

字体变化是运行到 if (ok) ui->pushButton_3->setFont(font);这行代码才生效,弹出的警告可以忽略

原本:void MainWindow::setText(const QString &string) // 插入文本

{

ui->textEdit->setText(string); // 将获取的文本添加到编辑器中

}

这样会将本来输入到文本框里的内容替换掉

修改后:void MainWindow::setText(const QString &string) // 插入文本

{

QString str = ui->textEdit->toPlainText();

// qDebug()<< str;

ui->plainTextEdit->setPlainText(str);

ui->textEdit->setText(string); // 将获取的文本添加到编辑器中

}

首先在ui界面里在加一个文本框,然后修改如上,插入后上文本框中的内容会添加到下文本框,添加的内容替代原本上文本框中的内容。

字符串变量

strings.xml包含整个应用程序中使用的字符串文件,字符串也可以在活动中创建来储存文本值。变量是指在设备的内存中创建一个容器,以容纳各种类型的数据。字符串是一种数据类型,由字母,数字,符号和空格组成。

在活动中创建字符串:

1、声明变量使之可以使用。(声明一个名为strName的变量)

String strName;1

2、实例化变量,放置字符串数据在strName中。

getText()方法

在活动创建一个EditText对象以从EditText中查看检索数据,并使用findViewById()方法从布局找到EditText。例如:

EditText etName = (EditText) findViewById(R.id.editText1);

12

后可使用getText()方法来检索与该视图关联的文本信息,它需要被转换为字符串。例如:

strName = etName.getText().toString();1

此代码将检索从EditText上查看的文本和存储在变量的信息strName

setText()方法

使用getText()方法,必须先创建一个TextView对象,并使用该findViewById()方法来从布局中获取信息。例如:

TextView tvName = (TextView) findViewById(R.id.textView1);1

然后,更改tvName的文本,可以使用

tvName.setText(strName);1

这样TextView中就可以显示任何strName中储存的任何值。

除此之外,使用setText()可以使用+将字符串和文本结合在一起。hard coded text需要加引号,字符串变量不需要。例如:

tvName.setText("Hello " + strName + "'s World!");1

TextView的文本会读出Hello Willis’s World!

多个信号连接一个槽时,在槽里可以用QObject::sender()返回发送信号的对象的指针,返回类型为QObject*

demo中:

QPushButton *btn=qobject_cast<QPushButton*>(sender());//获取发送信号的按钮的指针

setPlainText()顾名思义,是设置纯文本的。
  而setText()参数除了可以设置为纯文本之外,还可以设置为一些简单的html格式的字符串,当然这些字符串是修饰一个字符串的。具体查看Qt的帮助文件。

#include <iostream>
using namespace std;

//第四步才看
class A;
class B;
typedef void (A::*Apointer)();
typedef void (B::*Bpointer)();

//第一步开始看
class A {
public:
void (A::*click)();
void onClicked(){
cout<<"按A上面的按钮,调用了自己的onClick函数!"<<endl;
}

//第四步才看
B* slotObj;
void TreatClickEvent(){
(slotObj->*(Bpointer)click)();
}
};


//第三步才看
class B {
public:
int x=5;
void onClicked(){
cout<<"按A上面的按钮,调用了B的onClick函数! 成员变量x的值为"<<x<<endl;
}
};

//第一步开始看:复习成员变量指针对于普通指针变量来说,其值是它所指向的地址,0表示空指针。
//而对于数据成员指针变量来说,其值是数据成员所在地址相对于对象起始地址的偏移值,空指针用-1表示。
void runMemberVariblePointer(A * obj, int A::* pMember) {
cout<<obj->*pMember<<endl;
}
//第一步开始看:复习成员函数指针
//1.成员函数指针通过引用操作符(.*)从对象或引用获取成员;
//2.成员函数指针通过箭头操作符(->*)从对象指针获取成员。
void runfuncName(A * obj, void (A::*func)()){
(obj->*func)();
}
//第一步看:组合成员变量指针和成员函数指针
void runfuncPointer(A * obj, void (A::*( A::*pfunc ))()){ //Apointer A::* pfunc
(obj->*(obj->*pfunc))();
}

//typedef void (A::*Apointer)();
//第二步才看
//typedef void (A::*(A::*Signal))();
typedef Apointer A::* Signal;
void connect(A* a, Signal signal, Apointer slot){ //void (A::*slot)()
a->*signal = slot;
}
//第三步才看
void connect(A* a, Signal signal, Bpointer slot){
a->*signal = (Apointer) slot;
}
//第四步才看
void connect(A* a, Signal signal, B* b, Bpointer slot){
a->*signal = (Apointer) slot;
a->slotObj = b;
}

int main(int argc, char *argv[])
{
//第一步、理解信号的本质:成员函数指针类型的特殊成员变量
//第二步、连接A本身的信号与槽
A a;
runfuncName(&a,&A::onClicked);
connect(&a,&A::click,&A::onClicked);//a.click = &A::onClicked;
(a.*a.click)();
runfuncPointer(&a,&A::click);

//第三步:连接A的信号到B的槽
B b; B * fb = &b;
connect(&a, &A::click, &B::onClicked);//a.click = (void (A::*)())&B::onClicked;
(a.*a.click)();
(b.*(Bpointer)a.click)();//(fb->*(Bpointer)a.click)();

//第四步:完善连接A的信号到B的槽
connect(&a, &A::click,
fb, &B::onClicked);
a.TreatClickEvent();

return 0;
}
//成员指针和普通指针的区别
//成员指针通常指向一个类的成员,而不是对象中成员的特定实例。
//成员指针并不是真正的指针,它只是成员在对象中的偏移量。
//一般函数指针和成员函数指针的区别
//类的静态成员函数采用与一般函数指针相同的调用方式,而受this指针的影响,类的非静态成员函数与一般函数指针是不兼容的。
//而且,不同类的this指针是不一样的,因此,指向不同类的非静态成员函数的指针也是不兼容的。指向类的非静态成员函数的指针,在声明时就需要添加类名。
//
//考考你:成员指针和普通指针有什么区别?

//帮帮我:组合成员变量指针的用法及什么时候用?

首先将光标定位到函数上,然后按下F1键,打开函数的帮助文档
widget的默认大小就是他所包含的子部件的大小,且出现在窗口上的位置也是不确定的
qDebug()函数两种输出方法,第一种直接将字符串当做参数传给函数,另一种使用输出流的方式一次输出多个值,他们的类型可以不同,如果使用第二种方法必须添加头文件
帮帮我 为什么geometry 的值是640*480+0+0,frame的值为639*479+0+0
考考你为什么使用了new操作符为lable2分配了空间,却没有使用delete进行释放?

qt开始运行,没有反应,后来发现是因为文件路径里含有中文;
代码:
a.h:
#ifndef A_H
#define A_H
#include "b.h"
class A
{
private:
B b;
public:
A();
void doSomething();
B &getB();
};

#endif // A_H

b.h:
#ifndef B_H
#define B_H
class A;
class B{
private:
A *a;
public:
void doSomething();
A* &getA();
};
#endif // B_H

a.cpp:
#include <iostream>

using namespace std;
#include "a.h"

A::A(){
b.getA()=this;
}

void A::doSomething(){
b.doSomething();
}

B &A::getB(){
return b;
}

b.cpp:
#include <iostream>
using namespace std;

#include "a.h"
#include "b.h"

void B::doSomething(){
cout<<"OK"<<endl;
}

A* &B::getA(){
return a;
}

main.cpp:
#include <iostream>

using namespace std;
#include "a.h"
#include "b.h"

int main(int argc,char *argv[])//可以直接去掉括号里的内容
{
A *a = new A;
a->getB().doSomething();
return 0;
}

考考你: b.getA()=this;去掉会怎么样?事实上没有影响
A *&B去掉&会怎么样?

帮帮我:除了这样还有其他方法吗?


#include <iostream>
using namespace std;
/*B does not name type:
1.将B提到A前边,适用于简单代码
2.作前向引用说明,qt不支持;
3.将b作为头文件使用,适用于大程序,把引起互相包含的部分拿出来,写成另外一个文件,就避免了这些问题;
不要互相依赖:循环依赖是指两个模块直接或者间接地互相依赖。所谓模块就是一个紧凑的发布单元。
互相依赖的多个模块并不是真正的独立模块,而是紧紧胶着在一起的一个更大的模块,一个更大的发布单元。
因此,循环依赖有碍于模块性,是大型项目的祸根。请避免循环依赖。
*/
class A
{
private:
B b;
public:
void doSomething();
};

void A::doSomething()
{ b.doSomething(); }

class B
{
public:
void doSomething();
};

void B::doSomething()
{ cout<<"OK"<<endl; }

int main(int argc, char *argv[])
{
A * a = new A;
a->doSomething();
return 0;
}
//考考你:怎样解决类的组合问题?
//帮帮我:怎样解决类的循环依赖问题?


分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP