I created test QML application to show screen size.
It tested on Xiaomi Redmi 6. Device screen resolution is 720 x 1440 pixels.
I have got 360 x 696. Any ideas?
Windows 7 64 bit, Qt 5.14.1, jdk1.8.0_241.
main.qml:
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 720
height: 1440
title: qsTr("Hello World")
Column {
anchors.centerIn: parent
Text {
text: "Screen.width: " + Screen.width
color: "lightsteelblue"
}
Text {
text: "Screen.height: " + Screen.height
color: "lightsteelblue"
}
}
MouseArea {
anchors.fill: parent
onClicked: {
// ScreenSize == QGuiApplication::primaryScreen()->size()
console.log( ScreenSize.height, ScreenSize.width);
}
}
}
console output:
D libTest2_armeabi-v7a.so: qml: 696 360
I made like this: DPI Awareness.
This answer helped me.
int main(int argc, char *argv[])
{
argc = 3;
argv[0] = (char*)"Appname";
argv[1] = (char*)"--platform";
argv[2] = (char*)"android:dpiawareness=0";
QGuiApplication app(argc, argv);
...
}
I changed "windows" to "android".
Now it works correctly.
Although feature don't design for android.
After I delete append code string and it works correctly anyway.
Application works good in the initial state.
Something switched into Qt.
Related
I want to make a game overlay to show my custom cross-hair. I want it to be always there with no closing policy.
I used a Popup item in an ApplicationWindow and I set the opacity of it to 0 and the opacity of the pop-up to 1 but it just showed me nothing.I also tried using the pop-up item without any toplevel window but again nothing.
The question is "Is it possible to show an always-on-top popup without any visible top-level window ?"
Your suggestions would be appreciated.
Without a popup window, we can try out with the 'z' property of the QQuickItem. Stack the crosshair always on top of your other items. And if you want to move the crosshair across the screen you can use their 'x,y' properties.
I have tried a simple sample for the same. Used an Image item for crosshair on top of the scroll view. It works as expected. I tried my way. We will see if some other idea's coming in.
Sample code here:
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
visible: true
width: 640
height: 480
// used here only to indicate image loading is going on
BusyIndicator {
id: busyindicatorId
visible: backgroundImgId.status === Image.Loading ||
crossImgId.status === Image.Loading
anchors.centerIn: parent
}
// background item
ScrollView {
anchors.fill: parent
anchors.margins: 10
clip: true
visible: !busyindicatorId.visible
Image {
id: backgroundImgId
source: "https://i.ibb.co/ZBNLvzb/andriod.jpg"
}
}
// crosshair item
Image {
id: crossImgId
z: 1
width: 100
height: width
visible: !busyindicatorId.visible
source: "https://i.ibb.co/SJFTLwN/cross.png"
anchors.centerIn: parent
}
}
Updates
Instantiated two windows of that one can be used for crosshair and have to set some window properties(transparent, alwaysontop) to show always on top. Let's have a look at this base code. Sample video
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQuickView>
#include <QScreen>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
QScreen *screen = QGuiApplication::primaryScreen();
QQuickView view;
view.setSource(QUrl(QStringLiteral("qrc:/crosshair.qml")));
view.setX(screen->geometry().width()/2 - view.width()/2);
view.setY(screen->geometry().height()/2 - view.height()/2);
view.setColor("transparent");
view.setFlags(Qt::SubWindow | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint);
view.show();
return app.exec();
}
//////////////// main.qml ////////////////
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
Window {
visible: true
visibility: "FullScreen"
objectName: "mainWindow"
// used here only to indicate image loading is going on
BusyIndicator {
id: busyindicatorId
visible: backgroundImgId.status === Image.Loading
anchors.centerIn: parent
}
// background item
ScrollView {
anchors.fill: parent
anchors.margins: 10
clip: true
visible: !busyindicatorId.visible
Image {
id: backgroundImgId
source: "https://i.ibb.co/ZBNLvzb/andriod.jpg"
}
}
}
//////////////// crosshair.qml ////////////////
import QtQuick 2.9
import QtQuick.Controls 2.2
Item {
width: 100
height: 100
// crosshair item
Image {
width: parent.width
height: parent.height
source: "https://i.ibb.co/SJFTLwN/cross.png"
}
}
I have this small example that does not work as i expected :
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick.Controls.Material 2.2
Window {
id: root
visible: true
width: 640
height: 480
property bool lightTheme: false
Material.theme: Material.Dark
Material.foreground: Material.color(Material.Red) // value is always material red #F44336 (from light theme)
onLightThemeChanged: {
Material.theme = lightTheme ? Material.Light : Material.Dark;
}
Button {
id: btn
width: 200
height: 200
anchors.centerIn: parent
text: "change theme"
onClicked: {
lightTheme = !lightTheme;
}
}
Text {
id: darkRed
text: "predefinedDarkThemeRed"
color: "#EF9A9A"
anchors.top: btn.bottom
anchors.horizontalCenter: btn.horizontalCenter
}
Text {
id: lightRed
text: "predefinedLightThemeRed"
color: "#F44336"
anchors.top: darkRed.bottom
anchors.left: darkRed.left
}
}
The issue is with the default Material.Red color being always picked from the Material.Light theme whatever theme i have selected.
However, when i don't set any Material.foreground, then it is white with the Material.Dark and dark with the Material.Light, and dynamically switched between those colors when the theme is changed, so everything is fine.
I would expected the same behaviour with a custom Material.foreground but it does not seem to work.
What is wrong here ?
Thank you.
Note: the app is run with options -style material args, and i am using Qt 5.9.3 or Qt 5.10.1
i think you missed a little nuance
add in .pro file
QT += quickcontrols2
in mine file add QQuickStyle::setStyle("Material");
#include <QQuickStyle>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
................
QQuickStyle::setStyle("Material");
//The style can also be specified as a path to a custom style, such as
//QQuickStyle::setStyle(":/mystyle");
................
return app.exec();
}
in your example, the result will be
when pressed
I'm using in my code KeyNavigation.tab property to make navigation workable in qml.
But the control SpinBoxis not working with it. for example if i have a control between it and the element i want it to navigate it wont respect the rule.
I'm going to illustrate with a real example.
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
and
main.qml
import QtQuick 2.9
import QtQuick.Controls 1.4
import QtQuick.Controls 2.0
ApplicationWindow {
id: window
title: "Stack"
visible: true
height: 200
width: 400
Item {
id: page
anchors.fill: parent
width:parent.width
height: parent.height
ScrollView {
id:scrollView
anchors.fill:parent
Column{
width:parent.width
spacing:10
TextField {
id:textField
KeyNavigation.tab: spinBox1
implicitHeight: 30
font.bold: true
}
SpinBox {
id: spinBox1
KeyNavigation.tab: spinBox2
width: 100
height: 30
editable: true
}
ComboBox {
id:comboBox
//KeyNavigation.tab: spinBox2
anchors.topMargin: 10
textRole: "text"
}
SpinBox {
id: spinBox2
KeyNavigation.tab: textField
width: 100
height: 30
editable: true
}
}
}
}
}
Here spinBox1 wont jump to spinBox2 if we use tab.
This was tested on a windows 10 OS
The version of Qt used is 5.11.1
For some reason, the QQuickKeyNavigationAttached::keyPressed() is not called if the attached property is set on the SpinBox itself instead of its TextInput. So, using the attached property on the contentItem is a workaround:
SpinBox {
Component.onCompleted: contentItem.KeyNavigation.tab = spinBox
}
I'm new to qml and I didn't really get its logic yet.
Here is my issue: I have a chartview with barseries, and I expect that when the user clicks on a bar, the bar chart changes.
So I clear the barSeries and append new data to it. But it causes a segmentation fault.
If I do the same processing from a button click, it works well.
Do you have any idea what is the problem, and how to fix it?
Below is a code sample.
main.qml
import QtQuick 2.7
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.0
import QtCharts 2.2
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("Chartview test")
Item {
id: histoView
property int globalForJs: 0
anchors.fill: parent
visible: true
Component.onCompleted: {
redraw();
}
signal redrawSignal()
ColumnLayout {
anchors.fill: parent
Button {
id:myBtn
anchors { top: parent.top; left: parent.left; leftMargin: 20 }
height: 30
width: 80
text: "new chart"
onClicked: {
console.debug("myBtn onClicked")
histoView.redrawSignal()
}
}
ChartView {
id: chartView
anchors { bottom: parent.bottom; left: parent.left; right: parent.right }
height: parent.height - 40
title: "chartview"
BarSeries {
id: mySeries
axisX: BarCategoryAxis { categories: [" "] }
axisY: ValueAxis {
id: ordinate
min:0
max:100
}
onClicked: {
console.debug("mySeries onClicked")
histoView.redrawSignal();
//myBtn.clicked()
}
}
}
}
function redraw() {
// clear data
mySeries.clear();
// add 5 new data
for (var i=0;i<5;i++) {
var tab=[];
globalForJs++;
tab.push(globalForJs);
mySeries.append("tutu"+i,tab);
}
// update Y axis maximum value
if (ordinate.max < globalForJs) {
ordinate.max = globalForJs + 10;
}
}
onRedrawSignal:redraw()
}
}
main.cpp
#include <QApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QLatin1String("qrc:/main.qml")));
return app.exec();
}
Short answer:
Looks like a bug in QGraphicsScene or Qt Charts' usage of it. Please report a bug at bugreports.qt.io.
Long answer (debugging crashes in Qt):
When you run into a crash where there's only QML, and nothing suspicious-looking going on in your C++ code, it's probably a bug in Qt. In order to increase the changes of the bug being fixed quickly, it's a good idea to get a stack trace, because the developer may spot a simple fix for it by looking at where it crashes. To get a stack trace, you'll have to build a debug build of Qt.
When debugging your application with a debug build of Qt, I can see that QGraphicsItem::mouseReleaseEvent() is calling a member function of an object that has been deleted. An easy way to verify this is to add some debug code to the destructor of QGraphicsItem that prints out the memory address of each object that is destroyed. In addition, add a line to the beginning of QGraphicsItem::mouseReleaseEvent() that uses qDebug()'s printf syntax (to avoid QGraphicsItem's << operator being called, which would cause a crash before it could print anything):
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index f2b8b66..9f2302d 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
## -1501,6 +1501,7 ## QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent)
*/
QGraphicsItem::~QGraphicsItem()
{
+ qDebug() << Q_FUNC_INFO << this;
if (d_ptr->isObject) {
QGraphicsObject *o = static_cast<QGraphicsObject *>(this);
QObjectPrivate *p = QObjectPrivate::get(o);
## -7328,6 +7329,7 ## void QGraphicsItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
*/
void QGraphicsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
+ qDebug("About to access %p\n", this);
if (event->button() == Qt::LeftButton && (flags() & ItemIsSelectable)) {
bool multiSelect = (event->modifiers() & Qt::ControlModifier) != 0;
if (event->scenePos() == event->buttonDownScenePos(Qt::LeftButton)) {
Build qtbase and then debug your application again. The stack trace will now look something like this (copied from Creator):
1 QGraphicsItem::flags qgraphicsitem.cpp 1854 0x6dcf8cf9
2 QGraphicsItem::mouseReleaseEvent qgraphicsitem.cpp 7333 0x6dd05003
3 QtCharts::Bar::mouseReleaseEvent bar.cpp 90 0x7ffd83fd4a9b
4 QGraphicsItem::sceneEvent qgraphicsitem.cpp 6845 0x6dd03ac6
5 QGraphicsScenePrivate::sendEvent qgraphicsscene.cpp 1251 0x6dd58732
6 QGraphicsScenePrivate::sendMouseEvent qgraphicsscene.cpp 1325 0x6dd594fd
7 QGraphicsScene::mouseReleaseEvent qgraphicsscene.cpp 4099 0x6dd52c26
8 QGraphicsScene::event qgraphicsscene.cpp 3412 0x6dd51423
9 QApplicationPrivate::notify_helper qapplication.cpp 3713 0x6d7772de
10 QApplication::notify qapplication.cpp 3085 0x6d771d83
11 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1013 0x6cf72c16
12 QCoreApplication::sendEvent qcoreapplication.h 231 0x6cf7d5f2
13 QtCharts::DeclarativeChart::mouseReleaseEvent declarativechart.cpp 850 0x7ffd876dd16a
14 QQuickItem::event qquickitem.cpp 7756 0x7ffd7e206583
15 QApplicationPrivate::notify_helper qapplication.cpp 3713 0x6d7772de
16 QApplication::notify qapplication.cpp 3085 0x6d771d83
17 QCoreApplication::notifyInternal2 qcoreapplication.cpp 1013 0x6cf72c16
18 QCoreApplication::sendEvent qcoreapplication.h 231 0x6cf7d5f2
19 QQuickWindow::sendEvent qquickwindow.cpp 2807 0x7ffd7e2305f9
20 QQuickWindowPrivate::deliverMouseEvent qquickwindow.cpp 1671 0x7ffd7e235df1
... <More>
Console output (shortened):
Debugging starts
QML debugging is enabled. Only use this in a safe environment.
QML Debugger: Waiting for connection on port 52234...
[...]
__cdecl QGraphicsItem::~QGraphicsItem(void) QGraphicsItem(0x2da77915480, parent=0x2da77b0fc00, pos=0,0, flags=(ItemIsSelectable))
[...]
About to access 0x2da77915480
You can see that the QGraphicsItem whose memory address is 0x2da77915480 is destroyed, and then its mouseReleaseEvent() function is called.
I've noticed a new DropArea component in Qt5. I'm trying to drag a file from Finder (Mac) but only onEntered method is called.
import QtQuick 2.0
Rectangle {
id: background;
color: "white";
width: 300;
height: 300;
DropArea {
id: dropArea;
anchors.fill: parent;
onEntered: {
background.color = "gray";
drag.accept (Qt.CopyAction);
console.log("onEntered");
}
onDropped: {
console.log ("onDropped");
}
onExited: {
bckground.color = "white";
console.log ("onExited");
}
}
}
and here is window creation code:
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QQuickView qmlView;
qmlView.setGeometry(0, 200, 600, 400);
qmlView.setResizeMode (QQuickView::SizeRootObjectToView);
qmlView.setSource(QUrl::fromLocalFile("/Users/ivann/Projects/QtGuiTestApp/testView.qml"));
qmlView.show();
return a.exec();
}
Am I missing something?
Seems to be a Mac-specific issue (it wokrs as expected on Linux at least). Filled a bugreport to Nokia: https://bugreports.qt.io/browse/QTBUG-27125
As stated in the link attached by chebum that feature is not supported by QtQuick on any platform at the time of this writing.
Only posting for letting it know to future readers.
QtQuick 5.2 supports drag and drop from external applications. See the example http://qt-project.org/doc/qt-5/qtquick-externaldraganddrop-example.html