这次说的是在做主界面时学到的一些东西。
1、若想动态添加控件(其中一种是占满一个布局)且完成布局(布局只有上下或左右两种的时候),可以在Qt Designer上拖入一个控件(此处用的listView),然后在上面布局(如图此处是用得水平布局),此时该控件是占满整个窗体的。

然后在代码中再加入另半部分布局,该布局父类为在Designer上的布局。
m_pRightLayout =newQStackedLayout(ui.horizontalLayout);
m_pRightLayout->addWidget(QWidget *widget);
2、上述代码是在右边加入了一个QStactkedLayout布局,并向布局中添加控件,该布局提供了一个在同一界面叠加多层控件的功能,通过索引index和setCurrentIndex(int index)来使得索引为index的控件显示在最上层。
3、setFixWidth(int w)设置了控件的宽度为w。在这里我用他控制了listView的宽度。
4、信号与槽的参数必须是相同的。
connect(ui.listView,SIGNAL(clicked(QModelIndex)),this,SLOT(itemClicked(QModelIndex)));
此处QModelIndex是一个索引,可以定位到model中的数据。
这个信号与槽的作用是为了完成左边listView中某一项的点击会使得右边相应的widget显示在最上面。
voidMainWindow::itemClicked(QModelIndex index)
{
m_pRightLayout->setCurrentIndex(index.row());
}
注:根据添加方式,左右两边的index是对应增加的,也就是说每一个新的好友所发的消息的index和这个好友的index是同一个值。
5、setEditable(bool)或setReadOnly(bool)实现的是某个控件中内容是否可以编辑。
6、要关联发送人和发送的消息,正确的添加消息到textEdit(我所设置的右边布局中的控件)上,需要一个Map类型来保存数据QMap
这样收到一个消息时
QTextEdit* pEdit =newQTextEdit();
m_idToEdit[strId] = pEdit;
m_pRightLayout->addWidget(pEdit);
就能保证每个发送人的消息正确的显示在其对应的textEdit上。
7、两个类的头文件不能互相包含,会报错,可以将其中一个头文件包含在另一个cpp中。如果不相互包含不能实现功能,说明设计的逻辑有错误。
8、信号与槽机制可以跨越类使用,即一个类可以发出信号,而需要做操作的类接收信号并用槽函数实现功能。比如当收到登陆成功的消息后要关闭登陆界面:
在TcpClientSocket类中要发出一个login()的signals,不需要实现该信号,然后在HsClient_Login中建立一个槽函数onLogin(),并实现它
voidHsClient_Login::onLogin()
{
close();
}
最后联系起信号与槽:
connect(m_pTcpClientSocket,SIGNAL(login()),this,SLOT(onLogin()));
即可实现该功能。
9、在判断收到的消息的发送人是否已经在listView中时,因为创建过一个QMap来存储发送人和对应要存储消息的QTextEdit指针,所以可以通过map的iterator来寻找发送人是否已经存在与列表中(开始我尝试遍历standardItem没有成功,如果有知道怎么做的可以来群交流或者评论给出您的建议)。
10、对于做为标志的int型的运用
之前在判断收到的反馈信息是登陆成功还是注册成功时也用到了专门创建的作为标志的int型。
intflag = 0;
for(QMap::iterator iter = m_idToEdit.begin(); iter != m_idToEdit.end(); iter++)
{
if(iter.key() == strId)
{
flag = 1;
break;
}
}
if(flag == 0)
{
QStandardItem *friendName =newQStandardItem(strId);
friendName->setEditable(false);
m_pModel->appendRow(friendName);
ui.listView->setModel(m_pModel);
QTextEdit* pEdit =newQTextEdit();
pEdit->setReadOnly(true);
m_idToEdit[strId] = pEdit;
m_pRightLayout->addWidget(pEdit);
}
此处用一个标志位来判断发送人是否存在,因为直接判断iter.key() != strId会多次创建新的好友,用标志位来确定后再进行创建就不会出问题。
11、若想在B类中调用A类的一个数据成员或函数来改变当前已经创建的A类的状态,不能在B类需要调用A类的地方直接A*a,或A a,这样会创建一个新的A的对象,不能修改当前已经存在的A类的状态。
12、最后的效果如图

网友评论