QT中文乱码

来源:互联网 发布:mac制作一个网页 编辑:程序博客网 时间:2024/06/08 05:57

让Qt应用程序只运行一个实例
鉴客 发布于 2010年10月21日 17时 (2评) 3人收藏此代码, 我要收藏(?)
在实际应用中,我们经常需要让应用程序只有一个实例,再打开新的文档或者页面时,只是替换现在的窗口或者新打开一个标签,而不是重新启动一次应用程序。Qt中是否可以做到这样呢,答案是肯定的,因为Qt本身可以直接调用系统API,肯定可以做到,但是我们希望找到一个跨平台的通用的解决方案。

这就要用到Qt的QLocalSocket,QLocalServer类了,这两个类从接口上看和网络通信socket没有区别,但是它并不是真正的网络API,只是模仿了而已。这两个类在Unix/Linux系统上采用Unix域socket实现,而在Windows上则采用有名管道(named pipe)来实现。

既然是网络API,那么思路就很简单了,应用程序启动时首先会去连一个服务器(这里通过应用程序的名字来标识,就像网络端口一样),如果连接失败,那么则自己是第一个实例,就创建这么一个服务器,否则将启动参数发送到服务器,然后自动退出,而服务器会在收到通知以后进行处理。

这些动作我想最好是放在创建Application实例后,因为Qt本身有很多操作没有Application实例是无法进行操作的(至少事件循环是在创立Application以后才能启动吧),因此最好的位置就是通过继承QApplicaiton或者QCoreApplication自定义一个 YourOwnApplication,然后在构造函数中进行,下面是一个示意。

首先是YourOwnApplication构造函数:



01    QString serverName = QCoreApplication::applicationName();
02     
03    QLocalSocket socket;
04    socket.connectToServer(serverName);
05     
06    if (socket.waitForConnected(500)) { //如果能够连接得上的话,将参数发送到服务器,然后退出
07     
08        QTextStream stream(&socket);
09        QStringList args = QCoreApplication::arguments();
10     
11        if (args.count() > 1)
12            stream << args.last();
13        else
14            stream << QString();
15        stream.flush();
16        socket.waitForBytesWritten();
17        qApp->quit();
18     
19        return;
20    }
21     
22    //运行到这里,说明没有实例在运行,那么创建服务器。
23     
24    m_localServer = new QLocalServer(this);
25     
26    connect(m_localServer, SIGNAL(newConnection()),
27                this, SLOT(newLocalSocketConnection())); //监听新到来的连接
28     
29    if (!m_localServer->listen(serverName)) {
30        if (m_localServer->serverError() == QAbstractSocket::AddressInUseError
31                && QFile::exists(m_localServer->serverName())) { //确保能够监听成功
32            QFile::remove(m_localServer->serverName());
33            m_localServer->listen(serverName);
34        }
35    }
36    // 这样就保证了新启动的程序在检测到有其他实例在运行时就会自动退出,
37    // 但是它发出的请求还没有被处理,
38    // 下面看一下处理函数,也就是前段代码中的newLocalSocketConnection()。
39     
40    QLocalSocket *socket = m_localServer->nextPendingConnection();
41     
42    if (!socket)
43            return;
44     
45    socket->waitForReadyRead(1000);
46    QTextStream stream(socket);
47    //其他处理
48     
49    delete socket;
50    mainWindow()->raise();
51    mainWindow()->activateWindow(); //记得激活窗口哦











以下的最小化到托盘依赖于关闭到托盘,虽然有点不常规,但代码是如此的简明...

01    //关闭到托盘---------
02    void Widget::closeEvent(QCloseEvent *e)
03    {
04        e->ignore();
05        this->hide();
06    }
07     
08     
09    //最小化到托盘----
10    void Widget::changeEvent(QEvent *e)
11    {
12        if((e->type()==QEvent::WindowStateChange)&&this->isMinimized())
13        {
14            QTimer::singleShot(100, this, SLOT(close()));
15        }
16    }





用Qt把数据写入Excel 中

[代码] cpp代码
view source
print?
01    QString fileName = QFileDialog::getSaveFileName(this, tr("Save File"),
02            "",
03            tr("file ( *.CSV)"));
04    if(fileName == "")
05        return;
06     
07    QTextCodec *code;
08    code = QTextCodec::codecForName("gb18030");
09     
10    std::string strbuffer = code->fromUnicode(fileName).data();
11    FILE *fileWrite = fopen( strbuffer.c_str(),"w");
12    QString strFemale = "Female Count";
13    QString strMale = "Male Count";
14    QString strPatientCount = "Patient Count";
15    QString str ="/n";
16    std::string strCountbuffer = code->fromUnicode(strFemale+","+
17        strMale+","+strPatientCount+str+QString().setNum(femaleCount)+","+
18        QString().setNum(maleCount)+","+QString().setNum(patientCount)).data();
19    QFile file;
20    file.open(fileWrite, QIODevice::WriteOnly);
21    file.write(strCountbuffer.c_str(), qstrlen(strCountbuffer.c_str()));      
22    file.close();









Qt 设置透明按钮其实很简单
鉴客 发布于 2010年10月21日 17时 (0评) 1人收藏此代码, 我要收藏(?)
看到网上的很多在讨论透明的问题,不过有个按钮让按钮透明方法其实很简单
标签: QT , 透明 , 按钮 , QPushButton
代码片段(1)
[代码] cpp代码
view source
print?
1    QPushButton *bt =new QPushButton(this);
2    bt->setText("ok");
3    bt->move(200,100);
4    bt->setFlat(true);//就是这句能够实现透明,真是意外的发现,希望对一些学习的朋友有点帮助









Qt 实现的拷贝文件夹的函数

[代码] cpp代码
view source
print?
01    #include <QDir>
02    #include <QFileInfoList>
03     
04    /**
05      qCopyDirectory -- 拷贝目录
06      fromDir : 源目录
07      toDir   : 目标目录
08      bCoverIfFileExists : ture:同名时覆盖  false:同名时返回false,终止拷贝
09      返回: ture拷贝成功 false:拷贝未完成
10    */
11    bool qCopyDirectory(const QDir& fromDir, const QDir& toDir, bool bCoverIfFileExists)
12    {
13        QDir formDir_ = fromDir;
14        QDir toDir_ = toDir;
15     
16        if(!toDir_.exists())
17        {
18            if(!toDir_.mkdir(toDir.absolutePath()))
19                return false;
20        }
21     
22        QFileInfoList fileInfoList = formDir_.entryInfoList();
23        foreach(QFileInfo fileInfo, fileInfoList)
24        {
25            if(fileInfo.fileName() == "." || fileInfo.fileName() == "..")
26                continue;
27     
28            //拷贝子目录
29            if(fileInfo.isDir())
30            {
31                //递归调用拷贝
32                if(!qCopyDirectory(fileInfo.filePath(), toDir_.filePath(fileInfo.fileName())))
33                    return false;
34            }
35            //拷贝子文件
36            else
37            {
38                if(bCoverIfFileExists && toDir_.exists(fileInfo.fileName()))
39                {
40                    toDir_.remove(fileInfo.fileName());
41                }
42                if(!QFile::copy(fileInfo.filePath(), toDir_.filePath(fileInfo.fileName())))
43                {
44                    return false;
45                }
46            }
47        }
48        return true;
49    }








QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF8"));
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF8"));
QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF8"));
qDebug()<<"不怕神一样的对手,就怕猪一样的队友";

或者使用这样输出

QTextCodec* codec = QTextCodec::codecForName("UTF8")
QString str = codec->toUnicode("不怕神一样的对手,就怕猪一样的队友");
qDebug()<<str;






Qt写Excel文件

      好多人遇到过这个问题,比如gemfield在工程机械上使用Qt编写的人机界面,想要实现黑匣子功能,也就是机器运行的信息每几秒就要存储一次。存储为excel格式是最放便的了,这样就不用gemfield再单独写个软件来解析它,而且得益于办公软件的普及,故障记录信息也可以方便的拷贝。
      把怎么把记录在Qt中存储为excel格式呢?
      方案是极其的简单,以至于令你都难以置信。
      gemfield写作本文的缘由也正基于此。在和青岛之光社区的奇才们讨论的时候,得到了一个有趣的事实,那就是文本文件也可以变成Excel电子表格。奥秘在于(你可以在windows下打开记事本或者在SYSZUX OS下打开gedit来做这个实验)在每行的各项数据之间加入tab键,在行与行之间加入换行键(这个是很自然的),然后保存的时候后缀名为xls即可。就像上面的暗示一样,在windows下和linux下均可实现这个技巧。
      因为黑匣子功能的特殊性,文件名最好是用时间表示。
      gemfield的程序如下:
************************coded by gemfield********************
    QDateTime gemfield_dt=QDateTime::currentDateTime();//获得当前系统的日期时间
    QDate date=gemfield_dt.date();//取日期
    QVariant gemfield_y=date.year();
    gemfield_year=gemfield_y.toString();
    QTime time=gemfield_dt.time();//取时间
    QVariant gemfield_s=time.second();
    gemfield_sec=("0"+gemfield_s.toString()).right(2);//获得秒的显示数
  
    QVariant gemfield_m=time.minute();
    gemfield_min=("0"+gemfield_m.toString()).right(2);//获得分的显示数
  
    QVariant gemfield_h=time.hour();
    gemfield_hour=("0"+gemfield_h.toString()).right(2);//获得小时的显示数
  
    QVariant gemfield_d=date.day();
    gemfield_day=("0"+gemfield_d.toString()).right(2);//获得日期的显示数
  
    QVariant gemfield_mon=date.month();
    gemfield_month=("0"+gemfield_mon.toString()).right(2);//获得月的显示数
    file_name=gemfield_year+"_"+gemfield_month+"_"+gemfield_day+"_"+gemfield_hour+"_"+gemfield_min+dotfix;
 
    QDir::setCurrent("/mnt/yaffs/gemfield");//因为此程序是交叉编译在SYSZUX PAD上运行,所以路径是linux形式,你在windows下试验时要改过来的。
     log_file=new QFile(file_name);
     if (!log_file->open(QIODevice::ReadWrite | QIODevice::Text))
        {
         qDebug()<<"file open error!";
         return;      
        }
      log_file->close();
****************************************************************
      这样就在构造函数中创建了一个以当前时间命名的xls电子表格文件。
      然后写入数据;
*********************coded by gemfield****************************
      if (!log_file->open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Append))
        {
         qDebug()<<"file open error!";
         return;      
        }
 
    QTextStream log(log_file);
    QString gemfield_t,gemfield_v,gemfield_ah,gemfield_jie;
    gemfield_t=gemfield_t.fromLocal8Bit("青岛之光社区");
    gemfield_v=gemfield_v.fromLocal8Bit("一支ge-le之葩");
    gemfield_ah=gemfield_ah.fromLocal8Bit("SYSZUX PAD");
    gemfield_jie=gemfield_jie.fromLocal8Bit("G币");
    log<<gemfield_t<<"/t"<<gemfield_v<<"/t"<<gemfield_ah<<"/t"<<gemfield_jie<<"/n";
    log<<"25/t"<<"36/t"<<"48/t"<<"45/n";
    log_file->close();
******************************************************************
      注意tab键和换行键的输入哦!






主函数app后加上这句:

    QTextCodec::setCodecForLocale(QTextCodec::codecForName("GB18030"));

然后是从UTF8编码到GB编码的字符串转换方法:
Quote:

    QString Utf8_To_GB(QString strText)
    {
        return QString::fromUtf8(strText.toLocal8Bit().data());
    }


至于从GB到UTF8,那大家就经常用了:
Quote:


    QString GB_To_Utf8(char *strText)
    {
        return QString::fromLocal8Bit(strText);
    }