admin 管理员组文章数量: 893893
QT 屏幕旋转的两种方式
1、方式一:
#include "mainwindow.h"
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsProxyWidget>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w_ui;QGraphicsScene *scene = new QGraphicsScene;QGraphicsProxyWidget *w = scene->addWidget(&w_ui);w->setRotation(90);QGraphicsView *view = new QGraphicsView(scene);view->show();return a.exec();
}
2、方式二:针对 linuxfb
(1) 修改linuxfb/qlinuxfbscreen.h,如下所示:
class QLinuxFbScreen : public QFbScreen
{Q_OBJECT
public:QLinuxFbScreen(const QStringList &args);~QLinuxFbScreen();bool initialize();QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE;QRegion doRedraw() Q_DECL_OVERRIDE;private:QStringList mArgs;int mFbFd;int mTtyFd;// add by immortal startint mRotation;// add by immortal endQImage mFbScreenImage;int mBytesPerLine;int mOldTtyMode;struct {uchar *data;int offset, size;} mMmap;QPainter *mBlitter;
};
(2) 修改linuxfb/qlinuxfbscreen.cpp,如下所示:
QLinuxFbScreen::QLinuxFbScreen(const QStringList &args)// : mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0) // modify by immortal: mArgs(args), mFbFd(-1), mTtyFd(-1), mBlitter(0),mRotation(0)
{mMmap.data = 0;
}QLinuxFbScreen::~QLinuxFbScreen()
{if (mFbFd != -1) {if (mMmap.data)munmap(mMmap.data - mMmap.offset, mMmap.size);close(mFbFd);}if (mTtyFd != -1)resetTty(mTtyFd, mOldTtyMode);delete mBlitter;
}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 by immorta startQRegularExpression rotationRx(QLatin1String("rotation=(0|90|180|270)"))// add by immorta endQString fbDevice, ttyDevice;QSize userMmSize;QRect userGeometry;bool doSwitchToGraphicsMode = true;// Parse argumentsforeach (const QString &arg, 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 by immortal startelse if (arg.contains(rotationRx, &match))mRotation = match.captured(1).toInt();// add by immortal 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 devicemFbFd = openFramebufferDevice(fbDevice);if (mFbFd == -1) {qErrnoWarning(errno, "Failed to open framebuffer %s", qPrintable(fbDevice));return false;}// Read the fixed and variable screen informationfb_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 by immortal startQRect originalGeometry = geometry;if( 90 == mRotation || 270 == mRotation ){int tmp = geometry.width();geometry.setWidth(geometry.height());geometry.setHeight(tmp);}// add by immortal endmGeometry = QRect(QPoint(0, 0), geometry.size());mFormat = determineFormat(vinfo, mDepth);// modify by immortal start// mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, geometry.size());mPhysicalSize = determinePhysicalSize(vinfo, userMmSize, originalGeometry.size());// modify by immortal end// mmap the framebuffermMmap.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;}// modify by immortal start
// mMmap.offset = geometry.y() * mBytesPerLine + geometry.x() * mDepth / 8;mMmap.offset = originalGeometry.y() * mBytesPerLine + originalGeometry.x() * mDepth / 8;// modify by immortal endmMmap.data = data + mMmap.offset;QFbScreen::initializeCompositor();// modify by immortal start// mFbScreenImage = QImage(mMmap.data, geometry.width(), geometry.height(), mBytesPerLine, mFormat);mFbScreenImage = QImage(mMmap.data, originalGeometry.width(), originalGeometry.height(), mBytesPerLine, mFormat);// modify by immortal endmCursor = 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);const QVector<QRect> rects = touched.rects();mBlitter->setCompositionMode(QPainter::CompositionMode_Source);for (int i = 0; i < rects.size(); ++i) // add by immortal 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 by immortal end mBlitter->drawImage(rects[i], *mScreenImage, rects[i]);// add by immortal startmBlitter->resetTransform();// add by immortal end}return touched;
}// grabWindow() grabs "from the screen" not from the backingstores.
// In linuxfb's case it will also include the mouse cursor.
QPixmap QLinuxFbScreen::grabWindow(WId wid, int x, int y, int width, int height) const
{if (!wid) {if (width < 0)width = mFbScreenImage.width() - x;if (height < 0)height = mFbScreenImage.height() - y;return QPixmap::fromImage(mFbScreenImage).copy(x, y, width, height);}QFbWindow *window = windowForId(wid);if (window) {const QRect geom = window->geometry();if (width < 0)width = geom.width() - x;if (height < 0)height = geom.height() - y;QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height));rect &= window->geometry();return QPixmap::fromImage(mFbScreenImage).copy(rect);}return QPixmap();
}
2,配置环境变量:
-
export QT_QPA_PLATFORM=linuxfb:fb=/dev/fb0
- 运行程序 ./test -platform linuxfb:fb=/dev/fb0:rotation=90
- rotation=90表示旋转90度。不加就默认不旋转
注:方式二完全参考:linuxfb旋转
方式二旋转之后屏幕原点好像有点问题,不过这个可以通过QT程序去解决。具体解决的原理,我还没有看懂。
非常感谢immortal018。复制过来只是做个备份。
以上两种方式,都测试过,可行。
本文标签: QT 屏幕旋转的两种方式
版权声明:本文标题:QT 屏幕旋转的两种方式 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1687604599h120182.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论