在 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 之后效果如下:
使用 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 窗口事件才能完美解决,待完成