QT 海思编程三两事
版本介绍
QT的版本为:5.14.0。
海思型号:3516。
QT界面无法显示中文
在 Windows PC 上C盘搜索 .ttf
会出现很多以此为后缀的字体,在这里我选择的是 simkai.ttf。 将其拷贝到板子上, 并且设置环境变量:
export QT_QPA_FONTDIR=$QT_ROOT/fonts
之后就可以在QT界面上显示中文了。
QT 界面旋转显示
为了将界面旋转90度,需要修改QT的源码 "qt-everywhere-src-5.14.0\qtbase\src\plugins\platforms\linuxfb"
具体修改参考如下,手残党直接for you:
qlinuxfbscreen.h
class QLinuxFbScreen : public QFbScreen
{
Q_OBJECT
public:
......
private:
//@ add for rotation
int mRotation;
......
};
qlinuxfbscreen.cpp
QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)
: mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0),mRotation(0)
{
mMmap.data = 0;
}
bool QLinuxFbScreen::initialize()
{
QRegularExpression ttyRx(QLatin1String("tty=(.*)"));
QRegularExpression fbRx(QLatin1String("fb=(.*)"));
QRegularExpression mmSizeRx(QLatin1String("mmsize=(\\d+)x(\\d+)"));
QRegularExpression sizeRx(QLatin1String("size=(\\d+)x(\\d+)"));
QRegularExpression offsetRx(QLatin1String("offset=(\\d+)x(\\d+)"));
//@ add for rotation
QRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"));
QString fbDevice, ttyDevice;
QSize userMmSize;
QRect userGeometry;
bool doSwitchToGraphicsMode = true;
// Parse arguments
for (const QString &arg : qAsConst(mArgs)) {
QRegularExpressionMatch match;
if (arg == QLatin1String("nographicsmodeswitch"))
doSwitchToGraphicsMode = false;
else if (arg.contains(mmSizeRx, &match))
userMmSize = QSize(match.captured(1).toInt(), match.captured(2).toInt());
else if (arg.contains(sizeRx, &match))
userGeometry.setSize(QSize(match.captured(1).toInt(), match.captured(2).toInt()));
else if (arg.contains(offsetRx, &match))
userGeometry.setTopLeft(QPoint(match.captured(1).toInt(), match.captured(2).toInt()));
else if (arg.contains(ttyRx, &match))
ttyDevice = match.captured(1);
else if (arg.contains(fbRx, &match))
fbDevice = match.captured(1);
//@ add for rotation start
else if(arg.contains(rotationRx,&match))
mRotation = match.captured(1).toInt();
//@ add for rotation end
}
if (fbDevice.isEmpty()) {
fbDevice = QLatin1String("/dev/fb0");
if (!QFile::exists(fbDevice))
fbDevice = QLatin1String("/dev/graphics/fb0");
if (!QFile::exists(fbDevice)) {
qWarning("Unable to figure out framebuffer device. Specify it manually.");
return false;
}
}
// Open the device
mFbFd = openFramebufferDevice(fbDevice);
if (mFbFd == -1) {
qErrnoWarning(errno, "Failed to open framebuffer %s", qPrintable(fbDevice));
return false;
}
// Read the fixed and variable screen information
fb_fix_screeninfo finfo;
fb_var_screeninfo vinfo;
memset(&vinfo, 0, sizeof(vinfo));
memset(&finfo, 0, sizeof(finfo));
if (ioctl(mFbFd, FBIOGET_FSCREENINFO, &finfo) != 0) {
qErrnoWarning(errno, "Error reading fixed information");
return false;
}
if (ioctl(mFbFd, FBIOGET_VSCREENINFO, &vinfo)) {
qErrnoWarning(errno, "Error reading variable information");
return false;
}
mDepth = determineDepth(vinfo);
mBytesPerLine = finfo.line_length;
QRect geometry = determineGeometry(vinfo, userGeometry);
//@ add for rotation start
QRect originalGeometry = geometry;
if(90 == mRotation || 270 == mRotation)
{
int tmp = geometry.width();
geometry.setWidth(geometry.height());
geometry.setHeight(tmp);
}
//@ add for rotation end
mGeometry = QRect(QPoint(0, 0), geometry.size());
mFormat = determineFormat(vinfo, mDepth);
//@ add for rotation start
//mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());
mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, originalGeometry.size());
//@ add for rotation end
// mmap the framebuffer
mMmap.size = finfo.smem_len;
uchar *data = (unsigned char *)mmap(0, mMmap.size, PROT_READ | PROT_WRITE, MAP_SHARED, mFbFd, 0);
if ((long)data == -1) {
qErrnoWarning(errno, "Failed to mmap framebuffer");
return false;
}
//@ add for rotation start
//mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;
mMmap.offset = originalGeometry.y() * mBytesPerLine + originalGeometry.x() * mDepth / 8;
//@ add for rotation end
mMmap.data = data + mMmap.offset;
QFbScreen::initializeCompositor();
//@ add for rotation start
//mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);
mFbScreenImage = QImage(mMmap.data, originalGeometry.width(), originalGeometry.height(), mBytesPerLine, mFormat);
//@ add for rotation end
mCursor = new QFbCursor(this);
mTtyFd = openTtyDevice(ttyDevice);
if (mTtyFd == -1)
qErrnoWarning(errno, "Failed to open tty");
switchToGraphicsMode(mTtyFd, doSwitchToGraphicsMode, &mOldTtyMode);
blankScreen(mFbFd, false);
return true;
}
QRegion QLinuxFbScreen::doRedraw()
{
QRegion touched = QFbScreen::doRedraw();
if (touched.isEmpty())
return touched;
if (!mBlitter)
mBlitter = new QPainter(&mFbScreenImage);
mBlitter->setCompositionMode(QPainter::CompositionMode_Source);
for (const QRect &rect : touched)
{
//@ add for rotation start
if(90 == mRotation || 270 == mRotation)
{
mBlitter->translate(mGeometry.height()/2,mGeometry.width()/2);
}
else if(180 == mRotation)
{
mBlitter->translate(mGeometry.width()/2,mGeometry.height()/2);
}
if(mRotation != 0)
{
mBlitter->rotate(mRotation);
mBlitter->translate(-mGeometry.width()/2, -mGeometry.height()/2);
}
//@ add for rotation end
mBlitter->drawImage(rect, mScreenImage, rect);
//@ add for rotation start
mBlitter->resetTransform();
//@ add for rotation end
}
return touched;
}
修改完成之后重新编译生成 libqlinuxfb.so ,将其替换之前的库文件,并且在程序运行之前进行设置:
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0:rotation=90
或者运行程序时加入参数:
./app -platform linuxfb:fb=/dev/fb0:rotatio=90
之后就可以看到旋转之后的界面。