Qt应用开发常用功能(持续更新)

Qt判断当前操作系统?

可使用宏判断,例如:

#ifdef Q_OS_MAC //mac
...
#endif
 
#ifdef Q_OS_LINUX //linux
...
#endif
 
#ifdef Q_OS_WIN32 //win
...
#endif

#ifdef __arm__ //arm
...
#endif

Qt实现应用程序关闭和重启?

//关机按钮-点击槽函数
void SystemD::on_shutdownButton_clicked()
{
    //关闭应用程序
    QCoreApplication::exit();
}

//重启按钮-点击槽函数
void SystemD::on_rebootButton_clicked()
{
    //重启应用程序
    qApp->quit();
    QProcess::startDetached(qApp->applicationFilePath(), QStringList());
}

Qt实现Linux下的系统关机和重启?

先使Linux的普通用户可以在不输入密码的情况下,执行sudo reboot命令实现重启,具体步骤可以参考我的另一篇博客 - Linux常见问题及解决方案 的第13小结。

//关机按钮-点击槽函数
void SystemD::on_shutdownButton_clicked()
{
	QProcess::execute("sudo halt"); //UBuntu下执行关机命令(需要root权限)
}

//重启按钮-点击槽函数
void SystemD::on_rebootButton_clicked()
{
    QProcess::execute("sudo reboot"); //UBuntu下执行重启命令(需要root权限)
}

Qt 实现Windows系统关机

第一种关机方法

#include <Windows.h>
#include <QProcess>

void ShutDown()
{
	QString program = "C:/WINDOWS/system32/shutdown.exe";
    QStringList arguments;
    arguments << "-s";
    QProcess *myProcess = new QProcess();
    myProcess->start(program, arguments);
}

第二种关机方法

#include <Windows.h>

void ShutDown()
{
	system("shutdown -s -t 00");
}

重启指令:shutdown -r -t xx
注销指令:shutdown -l -t xx

让Qt 程序休眠一段时间的方法

在Qt程序中,我们有时候会遇到这样的需求,比如让程序暂停(休息、休眠)一段时间。这里介绍以下几种方法:

一、阻塞型延时

阻塞的原理就是:在延时期间,本线程的事件循环得不到执行。

1、QThread类的sleep()

最简单的延时方法就是使用QThread类的sleep(n)、msleep(n)、usleep(n),这几个函数的不良后果就是,GUI会在延时的时间段内失去响应,界面卡死,所以,这三个函数一般只用在非GUI线程中。

QThread::sleep(5000);

2、使用定时器:死等

QTime timer = QTime::currentTime().addMSecs(5000);
while( QTime::currentTime() < timer ); //等待时间流逝5秒钟

这样做会存在一个问题,当在死循环的时候,我们的界面是无法刷新,用户是不会响应用户的任何交互的。也就是让用户感觉程序已经是假死状态了。

二、非阻塞延时

原理无非就是利用事件循环,有两种原理:

1、处理本线程的事件循环

在等待中,不断强制进入当前线程的事件循环,这样可以把堵塞的事件都处理掉,从而避免程序卡死。

QTime timer = QTime::currentTime().addMSecs(5000);
while( QTime::currentTime() < timer );
	QCoreApplication::processEvents(QEventLoop::AllEvents, 100);

QCoreApplication::processEvents(QEventLoop::AllEvents, 100);这条语句能够使程序在while等待期间,去处理一下本线程的事件循环,处理事件循环最多100ms必须返回本语句,如果提前处理完毕,则立即返回这条语句。这也就导致了该Delay_MSec函数的定时误差可能高达100ms。

2、使用子事件循环

创建子事件循环,在子事件循环中,父事件循环仍然是可以执行的。

QEventLoop eventloop;
QTimer::singleShot(5000, &eventloop, SLOT(quit())); //创建单次定时器,槽函数为事件循环的退出函数
eventloop.exec(); //事件循环开始执行,程序会卡在这里,直到定时时间到,本循环被退出

Qt实现右键菜单

// 初始化动作
QAction *newAction = new QAction("新建",this);
// 初始化右键菜单
QMenu *rightClickMenu = new QMenu(this);
// 动作添加到右键菜单
rightClickMenu->addAction(newAction);
rightClickMenu->addSeparator();
rightClickMenu->addAction(ui->exitAction);
// 给动作设置信号槽
connect(ui->exitAction, &QAction::triggered, this, &MainWindow::on_exitAction_triggered);

// 给控件设置上下文菜单策略:鼠标右键点击控件时会发送一个void QWidget::customContextMenuRequested(const QPoint &pos)信号
this->setContextMenuPolicy(Qt::CustomContextMenu);

Qt绑定回车键和确定按钮

输完密码在密码框按回车等同按了确定按钮的效果:

connect(m_pEditPasswd, SIGNAL(returnPressed()), this, SLOT(EnterSlot()));

注意:回车键同是包含键盘区的回车键和小键盘区的回车键。

加载指定字体文件

#ifdef Q_OS_WIN32
        // 加载字体(思源黑体)
        QString strFont = "./fonts/SourceHanSansCN-Normal-2.otf";
        if(!QFile::exists(strFont))
            strFont = "./fonts/msyh.ttf";
#else
        // 加载字体(思源黑体)
        QString strFont = "/usr/lib/fonts/SourceHanSansCN-Normal-2.otf";
        if(!QFile::exists(strFont))
            strFont = "/usr/lib/fonts/msyh.ttf";
#endif
        int id = QFontDatabase::addApplicationFont(strFont);  // 嵌入式字体加载指定路径
        if(QFontDatabase::applicationFontFamilies(id).size())
        {
            QString strFont = QFontDatabase::applicationFontFamilies(id).at(0);
            QFont font(strFont, 10);
            font.setPointSize(16);
            app.setFont(font);
        }

设置中文编码

//QTextCodec *codec = QTextCodec::codecForName("gbk");
//QTextCodec *codec = QTextCodec::codecForName("utf-8");
QTextCodec *codec = QTextCodec::codecForName("System");
QTextCodec::setCodecForLocale(codec);
QTextCodec::setCodecForCStrings(codec);
QTextCodec::setCodecForTr(codec);

使用 GBK 还是使用 UTF-8,依源文件中汉字使用的内码而定。一般代码源文件中文编码都是 UTF-8,所以代码也设置使用 UTF-8。也可以直接使用源文件的内置中文编码。

如何显示一个图片并使其随窗体同步缩放

下面给出一个从 QWidget 派生的类ImageWidget,来设置其背景为一个图片,并可随着窗体改变而改变,其实从下面的代码中可以引申出其它许多方法,如果需要的话,可以从这个类再派生出其它类来使用。

ImageWidget.h:

#ifndef IMAGEWIDGET_H
#define IMAGEWIDGET_H

#include <QtCore>
#include <QtGui>
class ImageWidget : public QWidget
{
Q_OBJECT
public:
	ImageWidget(QWidget *parent = 0, Qt::WindowFlags f = 0);

protected:
	void resizeEvent(QResizeEvent *event);
    
private:
	QImage _image;
};
#endif

ImageWidget.cpp:

#include "ImageWidget.h"

ImageWidget::ImageWidget(QWidget *parent, Qt::WindowFlags f)
: QWidget(parent, f)
{
    _image.load("image/image_background");
    setAutoFillBackground(true); // 这个属性一定要设置
    QPalette pal(palette());
    pal.setBrush(QPalette::Window,
    QBrush(_image.scaled(size(), Qt::IgnoreAspectRatio,
    Qt::SmoothTransformation)));
    setPalette(pal);
}

// 随着窗体变化而设置背景
void ImageWidget::resizeEvent(QResizeEvent *event)
{
    QWidget::resizeEvent(event);
    QPalette pal(palette());
    pal.setBrush(QPalette::Window,
    QBrush(_image.scaled(event->size(), Qt::IgnoreAspectRatio,
    Qt::SmoothTransformation)));
    setPalette(pal);
}

如何在窗体关闭前自行判断是否可关闭

重新实现这个窗体的 closeEvent()函数,加入判断操作:

void MainWindow::closeEvent(QCloseEvent *event)
{
    if (maybeSave())
    {
        writeSettings();
        event->accept();
    }
    else
    {
    	event->ignore();
    }
}

Qt打开文件与保存文件

// 打开文件
QString fileName;
fileName = QFileDialog::getOpenFileName(this,"Open File","","Text File(*.txt)");
if(fileName == "")
{
	return;
}
else
{
	QFile file(fileName);
	if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
	{
		QMessageBox::warning(this,"error","open file error!");
		return;
	}
	else
	{
		if(!file.isReadable())
			QMessageBox::warning(this,"error","this file is not readable!");
		else
		{
			QTextStream textStream(&file);
			while(!textStream.atEnd())
			{
				ui->textEdit->setPlainText(textStream.readAll());
			}
			ui->textEdit->show();
			file.close();
			flag_isOpen = 1;
			Last_FileName = fileName;
		}
	}
}

// 保存文件
QFileDialog fileDialog;
QString fileName = fileDialog.getSaveFileName(this, "save file", "", "Text File(*.txt)");
if(fileName == "")
{
    return;
}
QFile file(fileName);
if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
{
	QMessageBox::warning(this,"error","Open File Faile");
    return;
}
else
{
	QTextStream textString(&file);
	QString str = ui->textEdit->toPlainText();
	textString << str;
	Last_FileContent = str;
	file.close();
}

Qt实现截屏并保存

// 检查截图目录是否存在,若不存在则新建
QString strDir = QCoreApplication::applicationDirPath() + "/screenshot";
QDir dir;
if (!dir.exists(strDir))
{
	if(!dir.mkpath(strDir))
		QMessageBox::information(this, "Error", "新建截图目录失败!", QMessageBox::Ok);
}

// 截图并保存
QPixmap pix = this->grab(QRect(0,0,this->width(),this->height()));
QString fileName= QDateTime::currentDateTime().toString("yyyy-MM-dd-HH-mm-ss")  + ".png";//通过时间命名文件
if(!pix.save(QCoreApplication::applicationDirPath() + "/screenshot/" + fileName, "png"))
{
	QMessageBox::information(this, "Error", "保存错误 !", QMessageBox::Ok);
}
else
{
	QMessageBox::information(this, "Grab", "截图已保存在:安装目录\\Screenshot目录下!", QMessageBox::Ok);
}

QtCreator 屏蔽指定警告

有两种方法可以屏蔽指定警告。

方法一:

  1. Tools > Options > C++ > Code Model > Clang Code Model > Manage;
  2. 创建自己的配置,这里可以复制一份原来的配置 “Clang-only checks for almost everything (Copy)” ;
  3. 在Clang中添加要屏蔽的警告, 例如: -Wno-old-style-cast-Wno-deprecated-declarations
  4. 确定后选择刚刚创建的自己的配置。

例子:

img

  • 对应警告名称为: unused-variable
  • 格式为-Wno-警告名称
  • -Wno-unused-variable

方法二:

使用如下语句:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"

//这里写出现警告的代码就能实现去除警告(代码写在这中间)
 
#pragma clang diagnostic pop

正式发布版本关闭调试打印

#if IS_RELEASE_MODE
    // 默认先关闭qDebug()打印,以减少短时间内输出大量qDebug()打印造成的卡顿
    QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, false);

    // 如果执行./exeName d,则开放打印
    if(QString::fromUtf8(argv[1]) == "d") {
        printf("Open qDebug!!!!!\n");
        QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true);
    }
#endif

检测程序是Debug版还是Release版

#ifdef QT_NO_DEBUG  
qDebug() << "release mode";  
#else  
qDebug() << "debug mode";  
#endif

使用 findChildren 查找该控件下的所有子控件

// 查找指定类名objectName的控件
QList<QWidget *> widgets = fatherWidget.findChildren<QWidget *>("widgetname");

// 查找所有QPushButton
QList<QPushButton *> allPButtons = fatherWidget.findChildren<QPushButton *>();

// 查找一级子控件,不然会一直遍历所有子控件
QList<QPushButton *> childButtons = fatherWidget.findChildren<QPushButton *>(QString(), Qt::FindDirectChildrenOnly);

findChild 为查找单个

巧妙的使用inherits判断是否属于某种类

QTimer *timer = new QTimer;         // QTimer inherits QObject
timer->inherits("QTimer");          // returns true
timer->inherits("QObject");         // returns true
timer->inherits("QAbstractButton"); // returns false

Qt最小化后恢复界面假死冻结,加上代码

void showEvent(QShowEvent *e)
{
    setAttribute(Qt::WA_Mapped);
    QWidget::showEvent(e);
}

如果使用sqlite数据库不想产生数据库文件,可以创建内存数据库

QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(":memory:");

巧妙的用QEventLoop开启事件循环

巧妙的用QEventLoop开启事件循环,可以使得很多同步获取返回结果而不阻塞界面。QEventLoop 内部新建了线程执行。

QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();

Qt默认不支持大资源文件,比如添加了字体文件,需要pro文件开启

CONFIG += resources_big

Qt中继承QWidget之后,样式表不起作用

Qt中继承QWidget之后,样式表不起作用,解决办法有三个。强烈推荐方法一。

  • 方法一:设置属性 this->setAttribute(Qt::WA_StyledBackground, true);
  • 方法二:改成继承 QFrame,因为 QFrame 自带 paintEvent 函数已做了实现,在使用样式表时会进行解析和绘制。
  • 方法三:重新实现 QWidget 的 paintEvent 函数时,使用 QStylePainter 绘制。
void Widget::paintEvent(QPaintEvent *)
{
    QStyleOption option;
    option.initFrom(this);
    QPainter painter(this);
    style()->drawPrimitive(QStyle::PE_Widget, &option, &painter, this);
}

QFile 打开关闭的注意事项

在使用 QFile 的过程中,不建议频繁的打开文件写入然后再关闭文件,比如间隔 5ms 输出日志,IO 性能瓶颈很大,这种情况建议先打开文件不要关闭,等待合适的时机比如析构函数中或者日期变了需要重新变换日志文件的时候关闭文件。不然短时间内大量的打开关闭文件会很卡,文件越大越卡。

注意使用viewport

很多控件都带有 viewport,比如 QTextEdit/QTableWidget/QScrollArea,有时候对这些控件直接处理的时候发现不起作用,需要对其 viewport() 设置才行,比如设置滚动条区域背景透明,需要使用scrollArea->viewport()->setStyleSheet("background-color:transparent;");而不是scrollArea->setStyleSheet("QScrollArea{background-color:transparent;}");

注意使用setMouseTracking

有时候设置了鼠标跟踪 setMouseTracking 为真,如果该窗体上面还有其他控件,当鼠标移到其他控件上面的时候,父类的鼠标移动事件 MouseMove 识别不到了,此时需要用到 HoverMove 事件,需要先设置setAttribute(Qt::WA_Hover, true);

推荐使用 at() 取值而不是 [] 操作符

在我们使用 QList、QStringList、QByteArray 等链表或者数组的过程中,如果只需要取值,而不是赋值,强烈建议使用 at() 取值而不是 [] 操作符,在官方书籍《C++ GUI Qt 4编程(第二版)》的书中有特别的强调说明,此教材的原作者据说是 Qt 开发的核心人员编写的,所以还是比较权威,至于使用 at() 与使用 [] 操作符速度效率的比较,网上也有网友做过此类对比。

如何安全的删除Qt的对象类

安全的删除 Qt 的对象类,强烈建议使用 deleteLater 而不是 delete,因为 deleteLater 会选择在合适的时机进行释放,而 delete 会立即释放,很可能会出错崩溃。如果要批量删除对象集合,可以用 qDeleteAll,比如qDeleteAll(btns);

QProgressBar实用技巧

当将进度条控件的最大值、最小值都设置为 0 时,可以显示忙碌状态,从而替代百分比表示的进度。这在某些情况下,非常有用,例如:当用 QNetworkAccessManager 从远端服务器下载某个文件,而不知道文件多大、不知道要下载多久才能下载完成时,设置为忙碌状态就非常适用。

QLineEdit实用技巧

通过调用单行编辑框控件的 setClearButtonEnabled 方法,且向该方法传递 true 参数,当编辑框文本不为空时,则编辑框右边会出现一个圆形叉号,点击该叉号会清除文本;当编辑框没有文本时,右边圆形叉号不会出现。

m_pLineEdit->setClearButtonEnabled(true);

通过 setInputMask 函数设置掩码,如设置 IP,如下代码可以设置 IP:

ipLineEdit->setInputMask("000.000.000.000;0");
maskLineEdit->setInputMask("000.000.000.000;0");
gatewayLineEdit->setInputMask("000.000.000.000;0");
dnsLineEdit->setInputMask("000.000.000.000;0");

Qt获取多个屏幕分辨率

通过QDesktopWidget的screenGeometry方法获取多个屏幕的分辨率

获取QDesktopWidget

  • QDesktopWidget类提供了对多屏幕信息的访问

    QDesktopWidget *desktopWidget = QApplication::desktop();
    

使用screenGeometry方法获取分辨率

  • 接口方法

    const QRect QDesktopWidget::screenGeometry(int screen = -1) const
    
  • 获取默认屏幕分辨率

    QRect screenRect = desktopWidget->screenGeometry();
    screenRect.width();
    screenRect.height();
    
  • 获取其他外接屏幕分辨率将对应screen值传进screenGeometry中。

Qt简单屏幕截图(兼容Qt4/5)

  • Qt4使用QPixmap::grabWindow接口获取指定屏幕;
  • Qt5使用QScreen 的grabWindow接口获取指定屏幕;
  • QApplication::desktop()获取根窗口;
  • QUuid::createUuid()产生唯一ID;
  • pixmap.save(name)保存截图到本地.

main.cpp:

#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include <QPixmap>
#include <QUuid>
#include <QDateTime>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0))
    QPixmap pixmap = QPixmap::grabWindow(QApplication::desktop()->winId());
#else if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
    QScreen *screen = QGuiApplication::primaryScreen();
    QPixmap pixmap = screen->grabWindow(QApplication::desktop()->winId());
#endif

    QString name = QString("%1-%2.png").
            arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss")).
            arg(QUuid::createUuid().toString());

    pixmap.save(name);

    return 0;
}

为Qt程序添加启动图片

有时候程序加载过程中时间过长需要先加载图片以避免黑屏的尴尬。

用法1

  • 在显示splash.png图片过程中执行用户启动程序的初始工作,等待完成后调用finish即可关闭启动图片。

    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        QPixmap pixmap(":/splash.png"); // 装载图片
        QSplashScreen splash(pixmap); // 初始化图片到QSplashScreen
        splash.show(); // 显示图片
        app.processEvents(); // 刷新事件循环
        ...
        QMainWindow window;
        window.show();
        splash.finish(&window); // 完成后自动close
        return app.exec();
    }
    

用法2

  • 在加载过程中可以调用splash->showMessage("Message");来显示文字;
  • 如果想绘制图形通过设置pixmap的指针或重写void QSplashScreen::drawContents(QPainter *painter)接口即可。

Qt加载字体

本文介绍怎么设置系统内置字体和从外部加载字体。

查询系统支持的字体

QFontDatabase database;
foreach (const QString &family, database.families()) {
    qDebug()<<family;
}

设置全局字体

  • font内容为family查询到的字体名称

    QFont font("family");
    QApplication::setFont(font);
    

外部加载字体

  • 字体支持ttc或ttf格式加载;

  • 使用

    addApplicationFont
    

    可以为系统路径,也可以资源文件。

    int fontId = QFontDatabase::addApplicationFont("font.ttc");
    QStringList fontIDs = QFontDatabase::applicationFontFamilies(fontId);
    if (! fontIDs.isEmpty()) {
        QFont font(fontIDs.first());
        QApplication::setFont(font);
    }
    else {
        qDebug()<<"Failed to load font.";
    }
    

qmake转换Makefile

命令如下:

qmake -o Makefile xxx.pro

使用qmake生成vs项目文件

使用qmake生成生成 Visual Studio 2010 项目文件:

qmake -spec win32-msvc2010 -tp vc project.pro

Qt软键盘-发送按键事件

发送按键事件到当前聚焦的窗体,常应用于编写 Qt 软键盘。

获取当前聚焦的 QWidget:

QWidget *receiver = QApplication::focusWidget();
qDebug()<<"Send key event to focus widget "<<receiver->objectName();

装载 press与release事件:

  • key为按键键值(整型);

  • value为按键实际值(QString).

    QKeyEvent keyPress(QEvent::KeyPress,     key, Qt::NoModifier, value);
    QKeyEvent keyRelease(QEvent::KeyRelease, key, Qt::NoModifier, value);
    

发送按键事件:

QApplication::sendEvent(receiver, &keyPress);
QApplication::sendEvent(receiver, &keyRelease);

Qt加载库

Qt项目加载库文件,一般时在pro后缀的项目文件上添加。

方法1(常规情况)

  • 在unix系统上-L是连接库目录,而-l则为加载库的名字;

  • 在windows系统下则可以直接添加库;

  • unix系统测试库为:/usr/local/lib/libtest.so

  • windows系统测试库为:

    C:/mylibs/test.lib
    

    unix:LIBS += -L/usr/local/lib -ltest
    win32:LIBS += C:/mylibs/test.lib
    

方法2(特殊情况)

  • 库路径存在空格的情况下添加;

  • unix系统下则需要双引号(“”)包含库的路径;

  • windows系统下则需要包含库的路径名字。

    unix:LIBS += "-L/home/user/test libs" -ltest
    win32:LIBS += "C:/mylibs/test libs/test.lib"
    

总结

  • 上面两种方法无论是unix与windows库的加载方法都可以互为使用。

使用QDesktopServices打开资源文件

使用QDesktopServices打开文件目录或网络连接。

QDesktopServices类提供了访问常见桌面服务的方法。

许多桌面环境提供的服务可被应用程序用于执行常见任务,如打开网页,其方式既一致又考虑到用户的应用程序偏好。

该类包含为这些服务提供简单接口的函数,这些接口指示服务是否成功。

函数的作用是:打开外部应用程序中位于任意url的文件。对于与本地文件系统上的资源对应的URL (URL方案为“file”),将使用一个合适的应用程序来打开文件;否则,将使用web浏览器来获取和显示文件。

用户的桌面设置控制是否打开某些可执行文件类型进行浏览,或者是否执行它们。一些桌面环境被配置为禁止用户执行从非本地url获取的文件,或者在执行文件之前要求用户的许可。

打开本地文件或目录

  • 方式1

    QDesktopServices::openUrl(QUrl::fromLocalFile("C:\\Users\\User\\Documents"));
    
  • 方式2

    QDesktopServices::openUrl(QUrl::fromLocalFile("C:/Users/User/Documents"));
    
  • 方式3

    QDesktopServices::openUrl(QUrl::fromLocalFile("file:///C:/Users/User/Documents"));
    

打开网址

QDesktopServices::openUrl(QUrl("https://www.cnblogs.com/linuxAndMcu/"));

参考:QDesktopServices简介(QT打开网页或者资源管理器)

Qt中的四舍五入取整

利用 qRound 函数对数据进行四舍五入:

// 	qRound()函数返回最近的整数值,并且要求进位基数为1,否则只能自己写round函数
qreal valueA = 2.3;
qreal valueB = 2.7;
int iRet = qRound(valueA); //iRet = 2;
int iRetB = qRound(valueB); //iRetB = 3; 

Qt 判断两个矩形是否重叠

// 判断两个矩形是否重叠
bool isRectOverlap(QPoint leftTop1, QPoint rightBottom1, QPoint leftTop2, QPoint rightBottom2)
{
    // 算出两个矩形的 左 l,右 r,上 t,下 b
    int l1 = leftTop1.x() < rightBottom1.x() ? leftTop1.x() : rightBottom1.x();
    int r1 = leftTop1.x() >= rightBottom1.x() ? leftTop1.x() : rightBottom1.x();
    int t1 = leftTop1.y() < rightBottom1.y() ? leftTop1.y() : rightBottom1.y();
    int b1 = leftTop1.y() >= rightBottom1.y() ? leftTop1.y() : rightBottom1.y();

    int l2 = leftTop2.x() < rightBottom2.x() ? leftTop2.x() : rightBottom2.x();
    int r2 = leftTop2.x() >= rightBottom2.x() ? leftTop2.x() : rightBottom2.x();
    int t2 = leftTop2.y() < rightBottom2.y() ? leftTop2.y() : rightBottom2.y();
    int b2 = leftTop2.y() >= rightBottom2.y() ? leftTop2.y() : rightBottom2.y();

    // 不重合
    if (l1 > r2 ||  // rect1 的左 在 rect2 的 右边
        r1 < l2 || 	// rect1 的右 在 rect2 的 左边
        t1 > b2 ||	// rect1 的上 在 rect2 的 下边
        b1 < t2)	// rect1 的下 在 rect2 的 上边
        return false;
    else
        return true;
}

如何disconnect一个lambda匿名函数

QObject::disconnect(senderInstance, &Sender::mySignal, this, nullptr);

Qt识别文件类型的正确姿势

一般我们识别文件类型都是从文件的后缀区分,这样做可以识别出文件格式。但在Qt里有更好的实现方法。

以识别图片类型为例

一般识别图片类型方法:
虽然这一方法可以实现识别图片类型,但是维护起来相对困难。如果真的要识别所有的文件是否是图片类型,还需要添加更多的判断方法。

QString file("sample.jpg");
if (file.contains(".jpg") || 
    file.contains(".bmp") || 
    file.contains(".png")) {
    qDebug()<<"这是图片。";
}

使用Qt接口识别的方法(推荐) :
QMimeType类描述由MIME类型字符串表示的文件数据类型

QMimeDatabase db;
QMimeType mime = db.mimeTypeForFile("sample.bmp");
if (mime.name().startsWith("image/")) {
    qDebug()<<"这是图片。";
}

一些MIME类型常用对照表

类型 描述 示例
text 普通文本 text/plain, text/html, text/css, text/javascript
image 图像文件(包含动态gif) image/gif, image/png, image/jpeg, image/bmp, image/webp
audio 音频文件 audio/wav, audio/mpeg, audio/midi, audio/webm, audio/ogg
video 视频文件 video/mp4, video/x-flv, video/webm, video/ogg
application 二进制数据 application/xml, application/pdf

获取 含有汉字的QString 长度

QString tstr = QString("asb测试字串def“);
int ns =tstr.length();//ns =10;
int nl = tstr.toLocal8Bit().length(); //nl = 14;  获得实际的字符个数 (一个英文站一个字符,一个中文字符站两个字符)

获取Label中的字符串长宽

// 获取Label中的字符串长宽
QFontMetrics fontMetrics(item->font());
int fontWidth = fontMetrics.width(item->text());
int fontHeight = fontMetrics.height();

// 判断QLabel是否有换行:如果字符串的宽度超出View的宽度,则认为有换行
if(fontWidth >= m_pScrollArea->width()) {
factor = 2;
space = 14;
}

参考:

QT里实现Windows电脑三种关机方法

让QT 程序休眠一段时间的方法

QT延时/等待怎么写?阻塞延时/不阻塞延时/耗时代码的处理

QT实现快捷键的三种方式

QT 新建、打开 、保存文件

Qt5.QtCreator_屏蔽警告

Qt中通过代码设置控件的objectName,和通过objectName查找该控件


posted @ 2018-12-18 15:12  fengMisaka  阅读(1914)  评论(0)    收藏  举报