QTCreatot做一个多线程服务器,通信有问题

Toney_Ho 2012-02-11 09:33:32
QTCreator 做一个多线程TCP服务器,客户端以前别人就做好了,并定制了通信协议,现在我要用QT做一个服务器,要求能同时和多个客户机按通信协议通信。遇到了点问题,我调了很久都没解决,大家帮我看看。
通信协议是:
1. 服务器向客户机发送命令(GET);
2. 客户机发送START确认开始通信;
3. 服务器发送AGAIN允许客户机发送;
4. 接收客户机发送过来的信息并保存到缓冲区(QString)中;
5. 检索缓冲区有没有客户机发送过来的结束命令(FINISH);
6. 有:发送接收成功标志(SUCCESS)结束通信,存文件;
7. 没有:转3;
如此往复直到检索到缓冲区中有客户机发过来的结束标志。
服务器要求能同时向多个客户机发送GET命令,并发的接收客户机发过来的信息,并在收到结束标志后将收到的信息存文件,信息不能发生串扰。
我的思路:
1. 利用QT的多线程;
2. 并不是为每个连接上的用户开启一个线程,而是为每个需要通信的客户端开启一个线程;
3. 程序有GUI界面,每当有一个客户机连接到服务器以后在GUI上显示出来,并提供复选框,由用户勾选需要通信的客户端,并通过点击Get按钮向所选择的客户端发送GET命令,进行通信和信息处理;
问题是:
当我向多个客户发送GET的时候,程序偶尔会崩溃,偶尔成功但是保存的数据发生串扰(比如本来是客户1的数据却保存到了客户2的文件中)。我调了很久,没解决。
在线程的run()函数中:connect(sockfd, SIGNAL(readyRead()), this,SLOT(recvData()),Qt::DirectConnection);指定为Qt::DirectConnectio,那么recvData(),是否是在子线程之中执行?但是如果我指定为Qt::BlockingQueuedConnection程序通信依然存在问题。请问大家我的设计思想有没有问题,实现方法有没有问题。
主要代码如下,另附上源码包,http://download.csdn.net/detail/toney_ho/4058244
,大家可以下载下来调试运行一下,看是哪儿的问题,可能下载下来在QTCreator中容易看清楚点。
可能程序较长,大家耐心看一下共同进步。
//tcpserver.h
#ifndef TCPSERVER_H
#define TCPSERVER_H
#include "tcpthread.h"
#include <QTcpServer>
class tcpserver : public QTcpServer
{
Q_OBJECT
public:
explicit tcpserver(QObject *parent = 0);
//QList<int> clientDescriptorList;
signals:
void newRow(int);
void displayInfo(int,QString, int);
void updateBar(int, qint64);
void signal_send_command(int,int);
public slots:
void incomingConnection(int socketDescriptor);
void slot_send_command(int,int);
};
#endif
//tcpthread.h
#ifndef TCPTHREAD_H
#define TCPTHREAD_H
#include <QThread>
#include <QTcpSocket>
#include <QtNetwork>
#define SEND_AGIAN 2
#define FOUND_FINISH 3
#define SEND_SUCCESS 4
#define SEND_GET 10
#define FOUND_START 11
#define TEST_OTHER 98
#define DISPLAY_BUFFER 97
#define RECV_FILE_SUCCESS 99
#define SAVE_FILE_SUCCESS 100
#define GET "GET"
#define START "START"
#define AGAIN "AGIAN"
#define FINISH "FINISH"
#define SUCCESS "SUCCESS"
class QFile;
class QTcpSocket;
class TcpThread : public QThread
{
Q_OBJECT
public:
TcpThread(int socketDescriptor,int command, QObject *parent = 0);
void run();
QTcpSocket *sockfd;
int socketDescriptor;
int command;
signals:
void error(QTcpSocket::SocketError socketError);
void displayInfo(int,QString, int);
void updateBar(int, qint64);
public slots:
int processBuffer(QString );
void recvData();
};
#endif // TCPTHREAD_H
//widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include "tcpthread.h"
#include "tcpserver.h"
class QDialogButtonBox;
class QTcpSocket;
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
TcpThread *thread ;
private:
Ui::Widget *ui;
tcpserver tcpServer;
QTime *currenttime;
private slots:
void on_pushButtonClearLog_clicked();
void on_pushButtonSaveLog_clicked();
void on_quitButton_clicked();
void on_pushButtonGET_clicked();
void on_OkButton_clicked();
void addNewRow(int);
void displayInfo(int,QString, int);
void updateBar(int, qint64);

signals:
void signal_send_command(int, int);

};
#endif // WIDGET_H
//tcpserver.cpp
#include "tcpserver.h"
//构造函数
tcpserver::tcpserver(QObject *parent) :
QTcpServer(parent)
{
}
//重新定义了incomingConnection这个虚函数,
//开辟一个新的tcpsocket线程,从TcpServer获得socketDescriptor,
//并完成相应的信号连接
void tcpserver::incomingConnection(int socketDescriptor)
{
qDebug() <<socketDescriptor;
//clientDescriptorList.append(socketDescriptor);
emit newRow(socketDescriptor); //display new client
connect(this,SIGNAL(signal_send_command(int ,int)),this,SLOT(slot_send_command(int ,int)));
}
void tcpserver::slot_send_command(int sockDescriptor, int cmd)
{
TcpThread *thread = new TcpThread(sockDescriptor,cmd, this);
thread->start();
connect(thread,SIGNAL(finished()),this,SLOT(deleteLater()));
connect(thread,SIGNAL(displayInfo(int,QString,int)),this,SIGNAL(displayInfo(int,QString,int)));
connect(thread,SIGNAL(updateBar(int,qint64)),this,SIGNAL(updateBar(int,qint64)));
}
//tcpthread.cpp
#include "tcpthread.h"
#include <QtGui>
#include <QtNetwork>
//构造函数完成简单的赋值/
TcpThread::TcpThread(int socketDescriptor,int command, QObject *parent):
QThread(parent),socketDescriptor(socketDescriptor),command(command)
{
}

void TcpThread::run()
{
sockfd = new QTcpSocket;
if (!sockfd->setSocketDescriptor(socketDescriptor))
{
emit error(sockfd->error());
return;
}
sockfd -> write(GET);
emit this->displayInfo(socketDescriptor,sockfd->peerAddress().toString(), SEND_GET);
connect(sockfd, SIGNAL(readyRead()), this,SLOT(recvData()),Qt::DirectConnection);
exec();
}

void TcpThread::recvData() //接收数据
{
static qint64 bytesReceived = 0 ; //收到的总字节
static QString buffer = ""; //数据缓冲区

qint64 available = 0;
if ( ( available = sockfd ->bytesAvailable() ) > 0 )
{
bytesReceived += available;
buffer.append(sockfd ->readAll());

//更新进度条
emit this->updateBar(socketDescriptor, bytesReceived);
//display buffer
emit this->displayInfo(socketDescriptor,buffer, DISPLAY_BUFFER);

if ( processBuffer(buffer) == 1)
{
emit this->updateBar(socketDescriptor, 100); //更新进度条
goto GOTO_SEND_SUCCESS;
}
goto GOTO_SEND_AGAIN;

GOTO_SEND_SUCCESS:
//send SUCCESS
sockfd -> write(SUCCESS);
emit this-> displayInfo(socketDescriptor,sockfd->peerAddress().toString(), SEND_SUCCESS);
return;

GOTO_SEND_AGAIN:
//send AGIAN
emit this->displayInfo(socketDescriptor,sockfd->peerAddress().toString(), SEND_AGIAN);
if (-1 == sockfd -> write(AGAIN))
{
qDebug() << "write error";
return;
}
}
}

int TcpThread::processBuffer(QString buffer)
{
static int END_FLAG_FINISH = 0 ;
static int positionSTART = 0;
static int positionFINISH = 0;
static QHostAddress fileName ;
static QFile *localFile ;
static QString fileBuffer = ""; //file buffer

END_FLAG_FINISH = 0;
if (-1 != (positionSTART = buffer.indexOf(START)) ) //found START
{
if (-1 != (positionFINISH = buffer.indexOf(FINISH))) //found FINISH
{
emit this->displayInfo(socketDescriptor,sockfd->peerAddress().toString(), FOUND_FINISH);
END_FLAG_FINISH = 1;
fileBuffer = buffer.mid(positionSTART+36,positionFINISH -positionSTART - 36);

fileName = sockfd->peerAddress();
quint16 port = sockfd->peerPort();
localFile = new QFile(fileName.toString()+(tr(".%1").arg(port))); //用户端的IP地址作为保存文件名
if(!localFile->open(QFile::WriteOnly))
{
qDebug() << "open file error!";
return -1;
}
QByteArray filetemp = fileBuffer.toLatin1();
if ( -1 == ( localFile->write(filetemp.data(),qstrlen(filetemp.data()))))
{
qDebug() <<"write file error!";
}
localFile->close();
fileBuffer.clear();
emit this->displayInfo(socketDescriptor,sockfd->peerAddress().toString(), SAVE_FILE_SUCCESS);
return END_FLAG_FINISH;
}
}
return END_FLAG_FINISH;
}

...全文
1001 18 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
erwei1983 2013-05-13
  • 打赏
  • 举报
回复
我运行你的代码了。 但是: tcpserver::tcpserver(QObject *parent) : QTcpServer(parent) { } 有问题啊: 错误信息:\server\tcpserver.cpp:8: 错误:C2470: “parent”: 看起来像函数定义,但没有参数列表;跳过明显的函数体 不知道怎么回事啊。要怎么修改才能运行啊。
pzhuyy 2012-02-15
  • 打赏
  • 举报
回复
如何才能达到向某个或者某几个客户端发送命令的目的呢?

相当于要在界面中控制线程的工作状态,从这个思路来做,可以将thread类做成tcpserver类的public成员变量,然后在界面中tcpserver->thread->get()这样的方式来实现看看,当然也可以用类似信号的方式。
Toney_Ho 2012-02-15
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 pzhuyy 的回复:]

如何才能达到向某个或者某几个客户端发送命令的目的呢?

相当于要在界面中控制线程的工作状态,从这个思路来做,可以将thread类做成tcpserver类的public成员变量,然后在界面中tcpserver->thread->get()这样的方式来实现看看,当然也可以用类似信号的方式。
[/Quote]
只有试试看了
pzhuyy 2012-02-14
  • 打赏
  • 举报
回复
QT和VC不一样的地方在于,在VC中线程与界面之间通讯可以直接传一个界面指针过去即可。但QT这样不行,如果在线程中直接调用界面指针控制界面,会弹出一个Debug fail错误,提示非gui thread不能够操作界面之类。

QT与界面交互都用信号,你可以在界面(widget)中,connect(tcpservre,SIGNAL(sign()),this,SLOT(slot()));

在tcpserver类中
connect(thread,SIGNAL(sign()),this,SLOT(slot()));

在thread类中emit sign,达到数据传递以及与界面交互的功能。

你原来程序中的
//更新进度条
emit this->updateBar(socketDescriptor, bytesReceived);
我这儿都不能够生效。

Toney_Ho 2012-02-14
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 pzhuyy 的回复:]
QT和VC不一样的地方在于,在VC中线程与界面之间通讯可以直接传一个界面指针过去即可。但QT这样不行,如果在线程中直接调用界面指针控制界面,会弹出一个Debug fail错误,提示非gui thread不能够操作界面之类。

QT与界面交互都用信号,你可以在界面(widget)中,connect(tcpservre,SIGNAL(sign()),this,SLOT(slot()));

在……
[/Quote]
我原来程序中的
    
void displayInfo(int,QString, int);
void updateBar(int, qint64);

是可以生效的哈

现在如果是和所有当前连接的客户机通信没有问题了(为每个连接开启线程,收到发送命令之后会向所有线程发送发送命令信号,这样会向所有的客户机发送命令),但是如何才能达到向某个或者某几个客户端发送命令的目的呢?
pzhuyy 2012-02-13
  • 打赏
  • 举报
回复
是你的static变量不正确使用导致,你将buffer定义成thread类的成员变量,不要用static变量,就不会造成数据串扰的问题了。

已测试过。

如下方法

qint64 bytesReceived = 0 ;
QString strtemp;
strtemp.sprintf("%d",socketDescriptor);
qint64 available = 0;
available = sockfd->bytesAvailable();
if(available>0)
{

buffer.append(sockfd->readAll());
buffer.append(strtemp);
qDebug()<<buffer;
}

显示结果:

"15608156081560815608156081560815608156081560815608156081560815608156081560815608156081560815608156081560815608156081560815608156081560815608156081560815608"
"05548055480554805548055480554805548055480554805548055480554805548055480554805548055480554805548055480554805548055480554805548055480554805548055480554805548"

我发送的数据为一个客户端发0,一个客户端发1

个人建议,尽量不要使用自己不是很熟练的编程技巧。
pzhuyy 2012-02-13
  • 打赏
  • 举报
回复
参照一下官方的例子,
void FortuneServer::incomingConnection(int socketDescriptor)
{
QString fortune = fortunes.at(qrand() % fortunes.size());
FortuneThread *thread = new FortuneThread(socketDescriptor, fortune, this);
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}

官方的例子在examples\network\threadedfortuneserver

这里为每一个连接启动一个新的线程。
pzhuyy 2012-02-13
  • 打赏
  • 举报
回复
先下载回来看看。
碎炎 2012-02-13
  • 打赏
  • 举报
回复
你调试的时候输出主线程的threadID和执行recvData的threadID看看,我也不大确定,我现在写多线程都是直接继承QObject的moveToThread来写的

我看过QextSerialPort的源码,似乎它是在run函数里写了一个死循环,然后通过标志位来调用函数,这样的话因为在run纤程中调用的,就是子线程执行的函数
Toney_Ho 2012-02-13
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 pzhuyy 的回复:]
参照一下官方的例子,
void FortuneServer::incomingConnection(int socketDescriptor)
{
QString fortune = fortunes.at(qrand() % fortunes.size());
FortuneThread *thread = new FortuneThread(socketDescriptor, ……
[/Quote]

这个我之前也看过,但是在我这个程序中,如果每来一个连接就开启一个线程的话好像有点不对,比如:
例子中的run()函数:


void FortuneThread::run()
{
QTcpSocket tcpSocket;

if (!tcpSocket.setSocketDescriptor(socketDescriptor)) {
emit error(tcpSocket.error());
return;
}

//...

}


它的QTcpSocket tcpSocket;这个是在run()内部定义的,但是我的QTcpSocket *sockfd;是定义在
class TcpThread : public QThread
{
//...
}

之中的,因为TcpThread的slots函数:
public slots:
void recvData();
int processBuffer();

需要使用到sockfd,像我这样定义这样运行时会提示:
QObject: Cannot create children for a parent that is in a different thread.
如果像例子一样定义到run()内部,那编译时会提示在recvData()和processBuffer()中
:错误:'sokfd'在此作用域中尚未声明;
我又想能不能把recvData()和processBuffer()这两个函数的代码移动到run()内部,不要recvData()和processBuffer()这两个函数,但是在run()中
connect(sockfd, SIGNAL(readyRead()), this,SLOT(recvData()));

起不到作用了,还杂循环接收数据呢。moveToThread我也试过,从QObject继承一个子类出来,然后将线程中的代码都移动到这个子类的成员函数中去,但是给我提示错误:
QObject::moveToThread: Current thread ( 0x89a5cc8 ) is not the object's thread ( 0x896a6e8 ).
Cannot move to target thread ( 0x896a6e8 )
我纠结啊,呵呵。。。。
Toney_Ho 2012-02-13
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 pzhuyy 的回复:]
C++类的成员函数中使用静态变量的陷阱

C++类的成员函数中,使用static变量时,该变量是放在类存储区,而不是对象存储区,所以所有该类的对象共享该静态变量。

如以下代码:

#include <stdio.h>
#include <iostream>
using namespace std;

class Cs
{
public:
void t(void)
……
[/Quote]
哦,这个明白了.
pzhuyy 2012-02-13
  • 打赏
  • 举报
回复
C++类的成员函数中使用静态变量的陷阱

C++类的成员函数中,使用static变量时,该变量是放在类存储区,而不是对象存储区,所以所有该类的对象共享该静态变量。

如以下代码:

#include <stdio.h>
#include <iostream>
using namespace std;

class Cs
{
public:
void t(void)
{
static i=0;
cout<<i++<<endl;
}
};


int main(int argc, char* argv[])
{
Cs c1;
Cs c2;
Cs c3;
c1.t();
c2.t();
c3.t();
return 0;
}





最后输出的数字不是0,而是2
pzhuyy 2012-02-13
  • 打赏
  • 举报
回复
你定义一个类的成员变量bytesReceived ,然后在构造函数中将bytesReceived = 0。就如同你的socketDescriptor,command一样。

我明白你的意思是想要bytesReceived变量记录收到的记录长度,成员变量在类中作用域是整个类而不是只局限于recvData函数中。


以下内容摘自网上:

全局变量在类实例化一个对象以后,在每个对象内都会产生一个对象的变量;
而静态变量在类实例化一个对象以后,他是属于类的变量,并不会随着对象的增加而增加,任何方式改变了类的静态变量后,其他的对象访问到(通过一定方式)的静态变量都是改变以后的值。

所以说,静态变量只是类的变量!

经试验也证明,在实例化二次时(二个客户端连接),你的static buffer内容会串在一起。

可能我上一帖的语气欠妥,抱歉:)
Toney_Ho 2012-02-13
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 pzhuyy 的回复:]
是你的static变量不正确使用导致,你将buffer定义成thread类的成员变量,不要用static变量,就不会造成数据串扰的问题了。

已测试过。

如下方法

qint64 bytesReceived = 0 ;
QString strtemp;
strtemp.sprintf("%d",socketDescriptor);
qint64 available ……
[/Quote]
把所有的static都去掉?我定义成static的原意是:就拿qint64 bytesReceived = 0;这个来说,因为在线程中可能不止一次进入recvData();这个函数,那么如果不定义成static,在第二次进入recvData()的时候qint64 bytesReceived = 0;这一句不是又要被执行一次么?定义成static才会只在第一次进入的时候定义和初始化,是这样的吧。。。
Toney_Ho 2012-02-12
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 ao834391367 的回复:]

这个 goto语句一般不用的,你得意思是不是把所有客户端的信息都存到一起了 然后在存起来?我觉得多线程的时候设定的缓存puff多个线程同时写的时候会崩溃,觉得可能是这个缓存没设计好

引用 2 楼 toney_ho 的回复:

没人啊????
[/Quote]

我的意思是每个客户端发送过来的信息分开存储(也就是每个线程有自己独立的缓冲区),然后存文件,也就是说有几个线程和客户机通信最后就有会存几个文件。有可能是缓冲区的原因,因为我和单个客户的通信并没有多大问题。
首先TcpThread::recvData()的运行是不是在子线程里面?如果是在子线程里面,那么 TcpThread::recvData()里面定义的buffer是线程私有的么?还是这个buffer会和父进程中的其他线程共享这个变量?
我的意思是要将buffer设计成线程私有的变量,这样各个线程通信时就可以只管自己的缓冲区,在linux c中我知道可以用pthread_key_create()等实现变量的线程存储,请问在QT中应该怎么定义?
另:goto那个留在之后优化代码的时候修改。谢谢提醒。
  • 打赏
  • 举报
回复
这个 goto语句一般不用的,你得意思是不是把所有客户端的信息都存到一起了 然后在存起来?我觉得多线程的时候设定的缓存puff多个线程同时写的时候会崩溃,觉得可能是这个缓存没设计好

[Quote=引用 2 楼 toney_ho 的回复:]

没人啊????
[/Quote]
Toney_Ho 2012-02-12
  • 打赏
  • 举报
回复
没人啊????
Toney_Ho 2012-02-11
  • 打赏
  • 举报
回复
//widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QtNetwork>
#include <QtGui>

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

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

void Widget::on_OkButton_clicked()
{
ui->pushButtonGET->setEnabled(false);
connect(&tcpServer,SIGNAL(newRow(int)),this,SLOT(addNewRow(int)));

connect(this,SIGNAL(signal_send_command(int,int)),&tcpServer,SIGNAL(signal_send_command(int,int)));

connect(&tcpServer,SIGNAL(displayInfo(int,QString,int)),this,SLOT(displayInfo(int,QString,int)));
connect(&tcpServer,SIGNAL(updateBar(int,qint64)),this,SLOT(updateBar(int,qint64)));

ui->OkButton->setEnabled(false);
QApplication::setOverrideCursor(Qt::WaitCursor);

while (!tcpServer.isListening() && !tcpServer.listen(QHostAddress::Any,8010))
{
QMessageBox::StandardButton ret = QMessageBox::critical(this,tr("回环"),tr("无法开始测试: %1.")
.arg(tcpServer.errorString()),
QMessageBox::Retry | QMessageBox::Cancel);
if (ret == QMessageBox::Cancel)
return;
}
ui->statuslabel->setText(tr("监听端口:%1").arg("2012"));
}

void Widget::addNewRow(int peerSockfd)
{
ui->pushButtonGET->setEnabled(true);
int totalRow = ui->tableWidget->rowCount();

ui->tableWidget->insertRow(totalRow);
QLabel *labelIP = new QLabel;
labelIP->setText(tr("%1").arg(peerSockfd));
ui->tableWidget->setCellWidget(totalRow,0,labelIP);

QProgressBar *bar = new QProgressBar;
bar->setMaximum(100);
bar->setValue(0);
ui->tableWidget->setCellWidget(totalRow,1,bar);

QCheckBox *checkbox = new QCheckBox;
ui->tableWidget->setCellWidget(totalRow,2,checkbox);
}

void Widget::updateBar(int peerDes, qint64 byte_recieved)
{
int row = 0;
QLabel *des = new QLabel;
do
{
des = (QLabel*)ui->tableWidget->cellWidget(row,0);
row++;
}while (peerDes != des->text().toInt());
QProgressBar *bar = new QProgressBar;
bar = (QProgressBar*)ui->tableWidget->cellWidget(row - 1, 1);
bar ->setValue( byte_recieved);
}

void Widget::displayInfo(int sockdes, QString peerIP, int command)
{
switch(command)
{
case SEND_AGIAN:
ui->listWidget->addItem(tr("%1 - %2 -%3: Send AGAIN.").arg(sockdes).arg(peerIP).arg(currenttime->currentTime().toString()));
break;
case FOUND_FINISH:
ui->listWidget->addItem(tr("%1 - %2 -%3: Found FINISH.").arg(sockdes).arg(peerIP).arg(currenttime->currentTime().toString()));
break;
case SEND_SUCCESS:
ui->listWidget->addItem(tr("%1 - %2 -%3: Send SUCCESS.").arg(sockdes).arg(peerIP).arg(currenttime->currentTime().toString()));
break;
case SEND_GET:
ui->listWidget->addItem(tr("%1 - %2 -%3: Send GET.").arg(sockdes).arg(peerIP).arg(currenttime->currentTime().toString()));
break;
case FOUND_START:
ui->listWidget->addItem(tr("%1 - %2 -%3: Found START.").arg(sockdes).arg(peerIP).arg(currenttime->currentTime().toString()));
break;
case RECV_FILE_SUCCESS:
ui->listWidget->addItem(tr("%1 - %2 -%3: RECV file success.").arg(sockdes).arg(peerIP).arg(currenttime->currentTime().toString()));
break;
case SAVE_FILE_SUCCESS:
ui->listWidget->addItem(tr("%1 - %2 -%3: Save file success.").arg(sockdes).arg(peerIP).arg(currenttime->currentTime().toString()));
break;
case DISPLAY_BUFFER:
ui->listWidgetBuffer->clear();
ui->listWidgetBuffer->addItem("buffer = ");
ui->listWidgetBuffer->addItem(tr("%1 ").arg(peerIP));
break;
case TEST_OTHER:
ui->listWidget->addItem(tr("%1 - %2 -%3: Test OK...").arg(sockdes).arg(peerIP).arg(currenttime->currentTime().toString()));
break;
default :break;
}
}

void Widget::on_pushButtonGET_clicked()
{
QCheckBox *checkbox;
QLabel *label;
int all_row = ui->tableWidget->rowCount();
for(int i = 0; i < all_row; i++)
{
checkbox = (QCheckBox*)ui->tableWidget->cellWidget(i,2);
if (checkbox ->isChecked())
{
label = (QLabel*)ui->tableWidget->cellWidget(i, 0);
emit this->signal_send_command(label->text().toInt(), SEND_GET);
}
}
ui->pushButtonGET->setEnabled(false);
}

void Widget::on_pushButtonSaveLog_clicked()
{
QFile *logfile = new QFile("SYSLOG");
QString log;
//char *temp = (char *)malloc(1000);
logfile->open(QFile::ReadWrite);
/*while( logfile->read(temp,1000) != -1)
{
log += temp;
//temp.clear();
}*/
//free(temp);
for (int i = 0; i < ui->listWidget->count();i++)
{
log += ui->listWidget->item(i)->text();
log += '\n';
}
QByteArray bytearray = log.toLatin1();
logfile->write(bytearray.data(),qstrlen(bytearray.data()));
logfile->close();
ui->listWidget->addItem(tr(" ------%1 - Save system log file ------").arg(currenttime->currentTime().toString()));
}

void Widget::on_pushButtonClearLog_clicked()
{
ui->listWidget->clear();
}

void Widget::on_quitButton_clicked()
{
this->close();
}

//main.cpp

#include <QtGui/QApplication>
#include "widget.h"
#include <QTextCodec>
int main(int argc, char *argv[])
{
QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
QApplication a(argc, argv);
Widget w;
w.show();

return a.exec();
}

16,816

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧