调整窗口大小以匹配Qt中的屏幕大小

时间:2014-08-04 19:02:22

标签: c++ qt

在OpenGL术语中,我想要做的是修改Qt GUI的投影矩阵。

假装窗口是480x640。它显示为正常,并呈现为纹理。 然后我拍摄纹理,并在整个屏幕上拉伸它。

Qt有类似的东西吗?我不希望GUI看起来很好,并且在480x640平板电脑上有适当大小的文本,但随后它会在1536x2048平板电脑上加载,你需要一个放大镜来显示文本。

之前我在OpenGL中编写了自己的GUI,计算了vid.width / BASEWIDTH,vid.height / BASEHEIGHT比率,并将元素的模型视图矩阵相乘,以确保GUI始终填充屏幕并保持相同的大小 - - 显然这只能完美地提供宽高比是一样的,但我离题了。

我在Qt Quick中与布局混淆了一段时间,它提供了一些不错的锚定选项,但是如果父窗口较大,则无法扩展文本。或者我在这里遗漏了什么?

我写的OpenGL GUI有一些控制位置坐标的选项:

转换的原点(顶部,中间,底部,左侧,中间,右侧) PosIsPercentage(指定位置坐标是否被解释为屏幕宽度/高度的百分比)

这允许您将位置设置为距屏幕任意边缘的距离,或者您可以设置PosIsPercentage = true并将X值设置为75以使坐标始终为屏幕尺寸的3/4

还有一个SizeIsPercentage值,因此您可以将按钮设置为屏幕宽度的10%。

我在Qt Quick设计器中看到了其中的一些选项,但它们的表现并不像我期望的那样。

我知道这很难解释,所以这是一张图片来证明:

http://www.spaddlewit.com/QtLayoutProblem.png

(不是我用的是Qt,而是我遇到的问题的一个很好的例子)

2 个答案:

答案 0 :(得分:1)

根据屏幕的宽度和高度缩放项目的效果非常好,除非您移动到高DPI设备。更好的方法是根据默认字体的高度缩放项目。例如,Text项的默认字体大小在Qt支持的平台上始终清晰可读,无论DPI如何。您可以使用相同的原则来缩放字体大小;将默认字体大小乘以某个数量。

下面我快速模拟了您链接到的屏幕截图:

import QtQuick 2.3
import QtQuick.Controls 1.2

ApplicationWindow {
    id: window
    contentItem.implicitWidth: 640
    contentItem.implicitHeight: 480
    contentItem.minimumWidth: 640
    contentItem.minimumHeight: 480
    contentItem.maximumWidth: 1024
    contentItem.maximumHeight: 768

    /*
        With Qt 5.4, you can also use the new FontMetrics item,
        which saves you the overhead of creating a Text item:

        For example:

        FontMetrics {
            id: fontMetrics
        }

        Then:

        font.pixelSize: fontMetrics.font.pixelSize * 4
        anchors.margins: fontMetrics.implicitHeight * 2
    */
    Text {
        id: defaultText
    }

    Image {
        source: "http://cdn2.landscapehdwalls.com/wallpapers/1/perfect-green-hills-1197-1280x800.jpg"
    }

    Item {
        id: container
        anchors.fill: parent
        anchors.margins: defaultText.implicitHeight * 2

        Column {
            anchors.right: parent.right
            anchors.verticalCenter: parent.verticalCenter
            spacing: container.anchors.margins

            Text {
                id: yourGameText
                text: "Your Game!"
                font.pixelSize: defaultText.font.pixelSize * 4
                wrapMode: Text.Wrap
            }

            ListView {
                interactive: false
                anchors.right: parent.right
                width: yourGameText.width
                height: container.height * 0.3
                model: ["Play Game!", "Options", "Exit"]
                delegate: Button {
                    text: modelData
                    width: ListView.view.width
                }
            }
        }

        Row {
            anchors.left: parent.left
            anchors.bottom: parent.bottom
            spacing: container.anchors.margins

            Image {
                source: "http://www.facebookbrand.com/img/assets/asset.f.logo.lg.png"
                width: defaultText.implicitHeight * 3
                height: width
            }

            Image {
                source: "http://g.twimg.com/Twitter_logo_white.png"
                width: defaultText.implicitHeight * 3
                height: width
            }

            Image {
                source: "http://www.youtube.com/yt/brand/media/image/YouTube-logo-full_color.png"
                width: defaultText.implicitHeight * 3
                height: width
            }
        }
    }
}

窗口大小

我做的第一件事是设置窗口的默认,最小和最大尺寸。

缩放

接下来,我创建了一个空文本项,项目和文本大小将基于此项。它可能看起来像hackish,它有点,但它也很好用。正如评论中所提到的,在Qt 5.4中会有一个FontMetrics类型,您可以使用它而不是创建一个永远不会显示的Text项目。

另一种方法是使用Screen的pixelDensity属性。

边距

你说你想:

  

将位置设置为距屏幕任意边缘的距离

我通过创建填充窗口的Item,然后将窗口边缘的边距设置为默认字体的隐式高度的某个因素来实现。这确保了项目内的内容与窗口边缘的物理距离(例如,以毫米为单位)相同,而不管您正在查看它的设备的DPI。如果您希望窗口较大时距离较大,则可以改为:

anchors.margins: window.width * 0.1

字体大小

查看Text中的Column项。如果要确保文本在屏幕上的物理大小相同,可以将font.pixelSize设置为默认字体的大小乘以某个数量。再说一遍,如果您更愿意将其基于屏幕大小而不是DPI,那么您可以这样做:

font.pixelSize: window.height * 0.05

更多信息

Scalability文档也对此主题进行了很好的概述。

下面是正在运行的应用程序的屏幕截图:

mockup screenshot

答案 1 :(得分:0)

以下工作,但令人讨厌 - 您必须创建scaleWidth和scaleHeight函数并在其中包装任何常量坐标。 字体大小沿着屏幕的最短边缘缩放 - 此应用程序是仅限纵向的方向,因此它使用scaleWidth(pointSize)作为字体大小。

很高兴找到一个与QML设计器兼容的解决方案..有没有办法自动插入这个计算,之后可能在运行时的C ++代码中?

import QtQuick 2.2
import QtQuick.Window 2.1
import QtQuick.Controls 1.2

ApplicationWindow {
    id:window
    visible: true
    width: 480
    height: 640

    function scaleWidth(w)
    {
        return w * (width / 480.0)
    }
    function scaleHeight(h)
    {
        return h * (height / 640.0)
    }

    Text {
        id: defaultText
    }

    Image {
        id: image1
        x: 0
        y: 0
        width: window.width
        height: window.height
        fillMode: Image.Stretch
        source: "http://cdn2.landscapehdwalls.com/wallpapers/1/perfect-green-hills-1197-1280x800.jpg"

        Label {
            id: lblTitle
            x: 0
            y: scaleHeight(8)
            text: qsTr("Welcome to the App")
            anchors.horizontalCenter: parent.horizontalCenter
            font.pointSize: scaleWidth(36)
            horizontalAlignment: Text.AlignHCenter
        }

        Label {
            id: lblSubtitle
            x: 0
            text: qsTr("Login to Continue")
            font.pointSize: scaleWidth(24)
            anchors.top: lblTitle.bottom
            anchors.topMargin: scaleHeight(8)
            anchors.horizontalCenter: lblTitle.horizontalCenter
        }

        Item {
            id: itemCenterAlign
            x: 0
            y: 0
            width: 0
            height: 200
            anchors.horizontalCenter: parent.horizontalCenter
        }

        Label {
            id: lblUsername
            x: 0
            text: qsTr("Username:")
            anchors.top: lblSubtitle.bottom
            anchors.topMargin: scaleHeight(64)
            font.bold: true
            font.pointSize: scaleWidth(24)
            anchors.right: itemCenterAlign.left
            anchors.rightMargin: scaleWidth(8)
        }

        TextField {
            id: txtUsername
            width: scaleWidth(224)
            height: scaleHeight(43)
            anchors.left: itemCenterAlign.right
            anchors.leftMargin: scaleWidth(8)
            anchors.top: lblSubtitle.bottom
            anchors.topMargin: scaleHeight(64)
            font.pointSize: scaleWidth(24)
            placeholderText: qsTr("Username")
        }

        Label {
            id: lblPIN
            x: 0
            y: scaleWidth(-8)
            text: qsTr("PIN:")
            font.bold: true
            font.pointSize: scaleWidth(24)
            anchors.topMargin: scaleHeight(12)
            anchors.right: itemCenterAlign.left
            anchors.rightMargin: scaleWidth(8)
            anchors.top: lblUsername.bottom
        }

        TextField {
            id: txtPIN
            x: 0
            y: 0
            width: scaleWidth(224)
            height: scaleHeight(43)
            placeholderText: qsTr("PIN")
            font.pointSize: scaleWidth(24)
            anchors.topMargin: scaleHeight(8)
            anchors.leftMargin: scaleWidth(8)
            anchors.left: itemCenterAlign.right
            anchors.top: txtUsername.bottom
        }

        Row {
            id: row1
            x: 0
            y: scaleHeight(277)
            width: scaleWidth(464)
            height: scaleHeight(115)
            spacing: scaleWidth(8)
            anchors.horizontalCenter: parent.horizontalCenter

            Button {
                id: cmdQuit
                text: qsTr("Quit")
                width: row1.width / 3 - row1.spacing / 2
                height: row1.height
            }
            Button {
                id: cmdGPSOnly
                text: qsTr("GPS Only")
                width: row1.width / 3 - row1.spacing / 2
                height: row1.height
            }
            Button {
                id: cmdLogin
                text: qsTr("Login")
                width: row1.width / 3 - row1.spacing / 2
                height: row1.height
            }
        }

        Button {
            id: cmdAbout
            width: cmdQuit.width
            height: scaleHeight(44)
            text: qsTr("About")
            anchors.top: row1.bottom
            anchors.topMargin: scaleHeight(8)
            anchors.left: row1.left
            anchors.leftMargin: 0
        }

        Label {
            id: lblVersion
            y: 619
            text: qsTr("v3.0.0.0")
            font.pointSize: scaleWidth(16)
            anchors.bottom: parent.bottom
            anchors.bottomMargin: scaleHeight(8)
            anchors.left: parent.left
            anchors.leftMargin: scaleWidth(8)
        }

        Label {
            id: lblBooks
            x: 0
            y: lvBooks.y
            text: qsTr("Books Loaded:")
            horizontalAlignment: Text.AlignRight
            font.pointSize: scaleWidth(24)
            anchors.right: lvBooks.left
            anchors.rightMargin: scaleWidth(8)
        }

        Rectangle
        {
            x: lvBooks.x
            y: lvBooks.y
            width: lvBooks.width
            height: lvBooks.height
            color: "white"
            border.color: "black"
        }

        ListView {
            id: lvBooks
            x: 0
            y: 0
            width: scaleWidth(224)
            height: scaleHeight(160)
            anchors.bottom: parent.bottom
            anchors.bottomMargin: scaleHeight(8)
            anchors.right: parent.right
            anchors.rightMargin: scaleWidth(8)
            model: ListModel {
                ListElement {
                    name: "Book1"
                }

                ListElement {
                    name: "Book2"
                }
            }
            delegate: Item {
                x: 5
                width: scaleWidth(80)
                height: scaleHeight(40)
                Row {
                    Text {
                        text: name
                        font.bold: true
                        font.pointSize: scaleWidth(24)
                        anchors.verticalCenter: parent.verticalCenter
                    }
                    spacing: 0
                }
            }
        }
    }
}