#w_out {
border:10px solid red;
}
#w_in {
border:5px solid green;
}
很明显 QFrame 的布局是以 border 为边界的,感觉这更符合一般的盒模型,而 Widget 的叠加起来了。一开始我以为是 QWidget 样式没生效,但是设置 setAttribute(Qt::WA_StyledBackground); 后还是一样的效果。
可以设置 setAttribute(Qt::WA_LayoutOnEntireRect) 使 QFrame 达到 QWidget 的效果,至于怎么达到 QFrame 的效果,目前没研究。
二、Qt Quick 问题交流 1.QSortFilterProxyModel 自动排序后,currentIndex 没有指向原来的值如数据 【1,3】,currentIndex = 1 指向3,这时候如果 1 修改为 4 触发自动排序,但是 currentIndex 还是 1 指向了 4 ,没有指向原来的 1。
自动排序时 proxy 的 sort 接口不会被调用,但是会触发 layoutAboutToBeChanged 和 layoutChanged 信号,通过这两个信号可以实现自动排序后指向原来的值所在行:(下图 idxTemp 为暂存自动排序之前的 currentIndex,排序完后再去找对应值所在行)
(Qt 5.15.2 实测无此 BUG)
ComboBox 设置 currentIndex 后,若有小部件访问 popup ,会导致只显示一个下拉选项,即使自定义了 popup 。临时的解决方法,可以在 onCompleted 时设置 currentIndex。
ComboBox{
id: control
//设置currentIndex后,若有小部件访问popup
//会导致只显示一个下拉选项,即使自定义了popup
//currentIndex: 1
model: [9,8,7,6]
contentItem: Text{
text: control.displayText
font: control.font
//任意小部件访问popup
color: control.popup.visible ? "red" : "green"
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
indicator: Rectangle{
width: 20
height: 20
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
//color: control.popup.visible ? "red" : "green"
}
//即使自定义了popup也会出现bug
//popup: Popup{ xxxx }
//临时的解决方法,可以在onCompleted时设置currentIndex
Component.onCompleted: currentIndex = 1;
}
3.Flickable/ListView 点击空白处没法获取点击信号
Flickable/ListView 是没有点击信号的,但是如果 interactive = true,默认开了交互效果,那么点击也不会穿透下去,虽然一般我们只给里面的组件设置点击,但是有时候需要点击某个区域获取焦点,这时候需要捕获点击。
如果在表面放一个不接受事件只过滤点击的 MouseArea,那么副作用是 cusorShape 也被他设置了,被覆盖 view 中的组件带的 cursorShape 没法正确呈现。
ListView {
anchors.fill: parent
model: 10
delegate: Rectangle{
width: ListView.view.width
height: 30
border.color: "red"
MouseArea{
anchors.fill: parent
cursorShape: Qt.BusyCursor
onClicked: {
console.log('click',index)
}
}
}
//不接受事件的mouse来捕获点击
MouseArea{
anchors.fill: parent
propagateComposedEvents: true
onPressed: {
console.log('clicked');
mouse.accepted = false;
}
}
}
目前我能想到的就是用事件过滤器,注册一个带过滤器的 QObject 子类到 QML 中,过滤 ListView 的点击信号。
bool MouseFilter::eventFilter(QObject *watched, QEvent *event)
{
Q_UNUSED(watched)
const int &&e_type = event->type();
switch(e_type)
{
case QEvent::MouseButtonPress:
emit press();
break;
case QEvent::MouseButtonRelease:
emit release();
break;
case QEvent::MouseButtonDblClick:
emit doubleClick();
break;
}
return false;
}
MouseFilter{
target: list_view
onPress: {
retrieval_area.forceActiveFocus();
}
}
三、其他
1.MSVC如果头文件写了execution_character_set,会导致include他的文件也具有该设置
头文件写了execution_character_set设置执行编码,导致include他的文件也具有该设置,和原本的编码设置不一致,导致乱码。
2.QMetaObject::invokeMethod 使用 QArgument 相关类或者宏作为参数QMetaObject::invokeMethod 使用 QArgument 相关类或者宏作为参数时,他是没有拷贝原值的,所以注意参数的生命周期。或者直接用 lambda 作为参数简单明了。
QMetaObject::invokeMethod(obj, "compute", Qt::DirectConnection,
Q_RETURN_ARG(QString, retVal),
Q_ARG(QString, "sqrt"),
Q_ARG(int, 42),
Q_ARG(double, 9.7));
参照 QTBUG-38398:[QTBUG-38398]与C++/CLR 库链接时,复制到剪贴板失败,出现CO_E_NOTINITIALIZED错误 - Qt Bug 跟踪器
在 Windows 上,Qt 是调用 COM 组件来实现剪贴板的,详情可以参照上面BUG链接。一个比较简单的处理方式就是将线程中处理好的数据发送到主线程,然后设置给剪贴板;或者调用 WINAPI 的剪贴板。
connect(&watcher,&QFutureWatcher::finished,[=]{
QImage img=watcher.result();
qDebug()grabWindow(0).toImage();
//QClipboard *board=QApplication::clipboard();
//board->setImage(img);
return img;
});
watcher.setFuture(future);
});