QT OpenGLWidget高分屏適配時出現的問題


參考官方文檔,為了解決4K屏幕顯示QT界面時出現窗口變小分辨率不匹配的問題,我們可以在 QApplication a(argc, argv); 這句之前添加:

#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
	QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
Constant Value Description
Qt::AA_EnableHighDpiScaling 20 Enables high-DPI scaling in Qt on supported platforms (see also High DPI Displays). Supported platforms are X11, Windows and Android. Enabling makes Qt scale the main (device independent) coordinate system according to display scale factors provided by the operating system. This corresponds to setting the QT_AUTO_SCREEN_SCALE_FACTOR environment variable to 1. This attribute must be set before QGuiApplication is constructed. This value was added in Qt 5.6.

運行結果顯示其他界面均運行正常,但是在 QOpenGLWidget 內,渲染的圖像只顯示在左下角,占整個渲染區域的 1/4 左右。

其原因是啟用 AA_EnableHighDpiScaling 后,QOpenGLWidget 內部的 OpenGL 不歸屬於 QT 的縮放范圍,所以我們需要自己縮放 QOpenGLWidget 內的像素尺寸。

解決方案

解決的方法就是自行獲取 devicePixelRatio,手動進行縮放。實現的方式大致有兩種,具體取決於你 QOpenGLWidget 裁剪的方式。ratio 可以通過 QApplication::desktop()->devicePixelRatio(); 獲取。

如果是通過 resizeGL(int width, int height) 裁剪,縮放就應寫在其中。
以下代碼參考了博文 https://blog.csdn.net/genispan/article/details/107864829

void QOpenGLWidget::resizeGL(int width, int height)
{
	makeCurrent();
	//參數X,Y指定了視見區域的左下角在窗口中的位置,一般情況下為(0,0),Width和Height指定了視見區域的寬度和高度。
    int ratio = QApplication::desktop()->devicePixelRatio();
	glViewport(0, 0, (GLint)width*ratio, (GLint)height*ratio);
	/*
	glMatrixMode設置當前矩陣模式:
	GL_MODEVIEW,對模型視景矩陣堆棧應用隨后的矩陣操作。
	GL_PROJECTION,對投影矩陣應用隨后的矩陣操作。
	GLTEXTURE,對紋理矩陣堆棧應用隨后的矩陣操作。
	*/
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	//glOrtho 參數分別代表(左下角x坐標,右上角x坐標,左下角y坐標,右上角y坐標)——坐標全相對於窗口左下角--原點)
	glOrtho(0, width*ratio, -height*ratio, 0, 0, 1); ///防止圖像上下翻轉
	glMatrixMode(GL_MODELVIEW);
	recalculatePosition();
	emit imageSizeChanged(mRenderWidth, mRenderHeight);
	updateScene();
}

裁剪實現在對輸入紋理的處理的話,相應的代碼應該寫到 paintGL() 內:

void QOpenGLWidget::initializeGL(){
    ...
    QScreen *pScreen = QApplication::desktop()->screen(screenNum)->screen();
	static const qreal NORMAL_DPI = 95.863739404014453;
	auto xFactor = pScreen->logicalDotsPerInchX() / NORMAL_DPI;
	auto yFactor = pScreen->logicalDotsPerInchY() / NORMAL_DPI;
	auto ratio = pScreen->devicePixelRatio();
	_xRatio = xFactor * ratio;
	_yRatio = yFactor * ratio;
}
void QOpenGLWidget::paintGL() {
    ...
    widgetWidth *= _xRatio;
	widgetHeight *= _yRatio;
    //QImage對象img即為輸入紋理
    auto img = currImg;
	if (!currImg.isNull()) {
		img = img.scaled(widgetWidth, widgetHeight, Qt::KeepAspectRatio);
		img = img.copy((img.width() - widgetWidth) / 2, (img.height() - widgetHeight) / 2, widgetWidth, widgetHeight);
    }
    ...
}

裁剪過后QOpenGLWidget應該就能正常顯示了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM