继续讲一些Qt开发中的技巧操作:
1.文本框的光标处理
正常情况下我们在文本框中输入,光标会一直伴随着我们的输入指向最后,有点像链表的next指针,但有时候文本框中的内容过长,而我们想要主动设置下将光标移到最前面的时候,可以用下面方法。
//下面三种方法都可以
//1.样式表方式设置属性“qproperty-cursorPosition”
QLineEdit{qproperty-cursorPosition:0;}
//2.调用“setSelection”方法
ui->lineEdit->setSelection(0, 0);
//3.调用“setCursorPosition”方法
ui->lineEdit->setCursorPosition(0);
2.数据库的int在视图中展示问题
用QSqlQueryModel+QTableView显示数据的时候,对于int类型的数据,你会发现,当数据值大于100万时,会变成科学计数显示,你可以对这一列加个空的委托就正常,但当int型数据大于1000万时,又变成科学计数显示了,所以需要终极大法,数值型,改为字串类型,重载数据模型显示。
ui->tableView->setItemDelegateForColumn(0, new QItemDelegate);
//下面是终极大法
QVariant SqlQueryModel::data(const QModelIndex &index, int role) const
{
QVariant value = QSqlQueryModel::data(index, role);
if (role == Qt::DisplayRole) {
int result = value.toInt();
if (result >= 1000000) {
//当数据大于100万的数值会被科学计数显示,这里转成字符串显示就正常了
value = QString::number(result);
}
}
return value
}
3.工程文件中区分系统及硬件平台
有时候做兼容跨平台的项目,可以在工程文件pro中区分不同的操作系统及硬件平台,实现一些特定处理。
win32 {}
unix {}
//Qt5可以直接用 linux{} Qt4切记需要用 unix:!maxc{}
unix:!maxc{}
linux {}
maxc {}
android {}
wasm {}
//表示64位平台
contains(QT_ARCH, x86_64) {}
//表示arm平台
contains(QT_ARCH, arm) || contains(QT_ARCH, arm64) {}
//万能办法直接切换到套件打印下 QT_ARCH 看下什么字符
message($$QT_ARCH)
其实我们添加一些第三方依赖库的时候,也会发现类似处理
4.图片的缩放显示
在显示视频画面以及一些图片展示的时候,一般会有三种机制作为参考:自动模式(超过则等比例缩放否则原图)、普通模式(任何尺寸都等比例缩放)、填充模式(任何尺寸都拉伸填充)。Qt中图片类QImage都提供了缩放策略的参数设置,比如Qt::KeepAspectRatio表示等比例缩放,但很多时候我们需要的是设置控件的大小,其实QSize类就提供了对应的方法scale专门解决这个问题,这个方法很容易被忽视。
//缩放显示模式
enum ScaleMode {
//自动模式(超过则等比例缩放否则原图)
ScaleMode_auto = 0,
//普通模式(任何尺寸都等比例缩放)
ScaleMode_normal = 1,
//填充模式(任何尺寸都拉伸填充)
ScaleMode_fill = 2
};
//传入图片尺寸和窗体区域及边框大小返回居中区域
static QRect getCenterRect(const QSize &imageSize, const QRect &widgetRect,
int borderWidth = 2, const ScaleMode &scaleMode = ScaleMode_auto)
{
QSize newSize = imageSize;
QSize widgetSize = widgetRect.size() - QSize(borderWidth * 2, borderWidth * 2);
if (scaleMode == ScaleMode_auto)
{
if (newSize.width() > widgetSize.width() || newSize.height() > widgetSize.height())
{
newSize.scale(widgetSize, Qt::KeepAspectRatio);
}
}
else if (scaleMode == ScaleMode_normal)
{
newSize.scale(widgetSize, Qt::KeepAspectRatio);
}
else
{
newSize = widgetSize;
}
int x = widgetRect.center().x() - newSize.width() / 2;
int y = widgetRect.center().y() - newSize.height() / 2;
return QRect(x, y, newSize.width(), newSize.height());
}
//传入图片尺寸和窗体尺寸及缩放策略返回合适尺寸的图片
static void getScaledImage(QImage &image, const QSize &widgetSize, const ScaleMode &scaleMode = ScaleMode_auto, bool fast = true)
{
Qt::TransformationMode mode = fast ? Qt::FastTransformation :
Qt::SmoothTransformation;
if (scaleMode == ScaleMode_auto)
{
if (image.width() > widgetSize.width() || image.height() > widgetSize.height()) {
image = image.scaled(widgetSize, Qt::KeepAspectRatio, mode);
}
} else if (scaleMode == ScaleMode_normal) {
image = image.scaled(widgetSize, Qt::KeepAspectRatio, mode);
} else {
image = image.scaled(widgetSize, Qt::IgnoreAspectRatio, mode);
}
}
5.单实例的妙用
设计模式中最基本也是最常用的一种模式“单实例”,但很多人却没有真正的应用起来。可以说,只要是被归为具有唯一资源的所有类,都可以将其作为单实例使用,比如,给设备上的摄像头做的控制类(只有一个摄像头),蜂鸣器的控制类,配置文件的控制类,自定义的弹框类,凡此类抽象,只要符合指向唯一实例对象的操作,都可将其设计为单实例类。
6.QChart图表的间距处理
在使用QChart图表控件的时候,你会发现默认的边距好大,有时候我们希望将界面做的紧凑一些,能显示更多的信息,所以需要设置边距来调整。
//设置背景区域圆角角度
chart->setBackgroundRoundness(0);
//设置内边界边距
chart->setMargins(QMargins(0, 0, 0, 0));
//设置外边界边距
chart->layout()->setContentsMargins(0, 0, 0, 0);
7.善于利用一些边框线做成绘制的效果
有时候,我们界面上主流是通过各种组件组合起来展示界面效果的,但UI非常轻佻的给你来几个交叉线,这就不太好通过组件进行布局了,你就得即考虑控件布局,也得考虑手动绘制,还得考虑这俩之间的Z序层叠问题。这时,一些组件的边框线或许可以比较巧妙的帮你避开难题。就像下图这样,ABCD是几个组件拼起来的同类型的自定义控件,这四个控件要用横竖交叉的虚线分割,如果用分割线实现这两条虚线,布局就不好操作,可以考虑用ABCD的外边框,做成虚线来实现一个模拟的交叉线,下图中的交叉虚线,其实就是A的左下边框线和D的左上边框线实现的。