您当前的位置: 首页 > 

龚建波

暂无认证

  • 3浏览

    0关注

    312博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

《QDebug 2022年3月》

龚建波 发布时间:2022-03-15 01:08:38 ,浏览量:3

一、Qt Widgets 问题交流 二、Qt Quick 问题交流 1.Quick.Control1 中 Menu 通过 style 设置样式不生效

在 Qt5 中设置 Control1 菜单组件的 style 之后,有时会发现样式并没有生效:

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Menu")

    Button {
        anchors.centerIn: parent
        text: "menu"
        onClicked: {
            menu.popup()
        }
    }

    Menu {
        id: menu
        style: MenuStyle {
            frame: Rectangle {
                border.color: "black"
                color: "gray"
            }
            itemDelegate.background: Rectangle {
                color: styleData.selected ? "orange" : "gray"
            }
            itemDelegate.label: Text {
                width: 60
                height: 30
                text: styleData.text
                font.pixelSize: 12
                font.family: "微软雅黑"
                color: "white"
                padding: 0
                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignHCenter
            }
        }
        MenuItem { text: "A" }
        MenuItem { text: "B" }
    }
}

这可能是因为我们使用的 QGuiApplication 而不是 QApplication,因为 Control1 很多地方是需要 Widgets 模块支持的。

QApplication app(argc, argv); //需导入 widgets 模块

使用 QApplication 之后效果如下:

2.一个 QML 类型定义循环依赖问题

使用 qmlRegisterType 注册 QML 组件到某个模块时,如果这个 QML 组件又因为需要访问一些变量或枚举又 import 了这个模块,就会导致循环依赖。

    qmlRegisterType("MyModule",1,0,"MyItem");
    qmlRegisterType(QUrl("qrc:/MyRect.qml"),"MyModule",1,0,"MyItem");
//MyRect.qml
import QtQuick 2.12
//又import了自己所在模块
import MyModule 1.0 

Rectangle {
}

部分情况会出现提示:

Cyclic dependency detected between "qrc:/MyRect.qml" and "qrc:/MyRect.qml"

但不是所有情况下都会有循环依赖的提示。

3.关于 ComboBox 和 Menu 等组件的 item delegate

这类组件,内部默认将 item 视为 Button 进行处理的,所以在自定义时最好用 Button 或者派生类型 ItemDelegate 之类的组件作为 delegate,点击时就会自动改变 currentIndex 等属性。这也避免了自己设置 View 的 currentIndex 后属性绑定失效的问题。

void QQuickComboBoxPrivate::createdItem(int index, QObject *object)
{
    Q_Q(QQuickComboBox);
    QQuickItem *item = qobject_cast(object);
    if (item && !item->parentItem()) {
        if (popup)
            item->setParentItem(popup->contentItem());
        else
            item->setParentItem(q);
        QQuickItemPrivate::get(item)->setCulled(true);
    }

    QQuickAbstractButton *button = qobject_cast(object);
    if (button) {
        button->setFocusPolicy(Qt::NoFocus);
        connect(button, &QQuickAbstractButton::clicked, this, &QQuickComboBoxPrivate::itemClicked);
        connect(button, &QQuickAbstractButton::hoveredChanged, this, &QQuickComboBoxPrivate::itemHovered);
    }

    if (index == currentIndex && !q->isEditable())
        updateCurrentTextAndValue();
}
ComboBox {
    id: control

    delegate: ItemDelegate {
        width: ListView.view.width
        text: control.textRole ? (Array.isArray(control.model) ? modelData[control.textRole] : model[control.textRole]) : modelData
        palette.text: control.palette.text
        palette.highlightedText: control.palette.highlightedText
        font.weight: control.currentIndex === index ? Font.DemiBold : Font.Normal
        highlighted: control.highlightedIndex === index
        hoverEnabled: control.hoverEnabled
    }
}
4.Control2 的 Dialog 或者 Popup 在不修改已有布局的情况下增加一个边框 

Popup 的 header、footer 和 contentItem 是竖向相接的挨在一起,三者的底部是 background。如果直接在 background 加边框,那会被上面的内容覆盖;如果在 contentItem 加边框,那没法覆盖 header 和 footer 区域。但 Control2 的 Popup 内容也和  Item 一样是在 Window 内统一渲染的,所以通过将坐标设置到 Popup 区域外部就可以不影响原有的布局,如:

import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Window 2.12

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("QML")

    Button {
        anchors.centerIn: parent
        text: "menu"
        onClicked: {
            pop.open()
        }
    }

    Dialog {
        id: pop
        modal: true
        width: 300
        height: 200
        anchors.centerIn: parent
        header: Rectangle {
            width: 300
            height: 30
            color: "blue"
            MouseArea {
                anchors.fill: parent
                onClicked: pop.close()
            }
        }
        contentItem: Rectangle {
            width: 300
            color: "orange"
        }
        background: Item {
            Rectangle {
                anchors.fill: parent
                anchors.margins: -1 //通过负外边距将范围设置到外部
                color: "green"
                border.color: "red"
            }
        }

        padding: 0
        margins: 1
        Rectangle {
            z: 1000
            anchors.fill: parent
            color: "green"
        }
    }
}
三、其他 1.无边框在Windows多屏下的一些问题

A.非主屏上执行以下操作会导致窗口最小化后不能恢复

window->showMaximized()
window->showNormal()
window->showMaximized()
点任务栏最小化
点任务栏恢复
window->showMinimized()
此时点任务栏图标不能恢复窗口

改为 win32 最小化后能正常恢复了

::ShowWindow((HWND)window->winId(),SW_SHOWMINIMIZED);

(QML有此问题,Widgets未复现,版本Qt5.13-5.15) 

B.窗口显示后,切换主屏设置,在原来的主屏上 showMaximized 最大化,会在范围外显示

改为 win32 最大化后解决,但是会遮住任务栏,所以重新设置了下范围

::ShowWindow((HWND)window->winId(),SW_SHOWMAXIMIZED);
if(window->screen()){
    window->setGeometry(window->screen()->availableGeometry());
}

(QML、Widgets都能复现,版本Qt5.13-5.15) 

C.非主屏 showMaximized 最大化会遮住任务栏

D.上面几种遮住任务栏的情况,如果 setGeometry 来调整显示区域,最小化后恢复还是挡住任务栏

E.综上,还是需要处理更多的 windows 窗口事件才能完美解决,待完成

关注
打赏
1655829268
查看更多评论
立即登录/注册

微信扫码登录

0.0624s