PDA

View Full Version : Android: resizeevent in qt 5.3.1 does not detect orientation change anymore



Cremers
23rd August 2014, 12:36
So I am looking at QScreenOrientationChangeEvent However I cannot seem to find *any* info on it. How do I implement it? Anybody some pointers please?

I tried this code in my mainwindow but it doesn't even fire.


bool MainWindow::event(QEvent *event)
{
if (event->type() == QEvent::OrientationChange)
{
QDesktopWidget desk;
mainwidth = desk.width(); // how do it get this stuff?
mainheight = desk.height();
}
return QWidget::event(event);
}

anda_skoa
23rd August 2014, 13:05
QScreen has a signal for orientation change.

You can get the screen(s) through QGuiApplication

Cheers,
_

Cremers
23rd August 2014, 13:27
Thanks for your answer.

This also works
connect(QApplication::desktop(), SIGNAL(resized(int)), this, SLOT(resized(int)));
but I need the orientation event in a qdialog too.

[rant] It can't be that the most important event on andriod has gone. All effort seems to go to xml while qwidget is not only ignored but even crippled. There's lots of code which just can't be ported to 5.3 this way.

Still hoping for a solution, else I will have to go back to 5.2 even if 5.3 is more stable on android.

anda_skoa
23rd August 2014, 13:38
Are you sure you are looking at the right receiver object for the event?
Try installing an event filter on the QApplication instance and see which object the event is sent to. I would imagine that it is sent to the QScreen, not any specific top level window.

Cheers,
_

Cremers
23rd August 2014, 14:03
Thanks for your help.
Which event are you talking about? If you mean the QScreenOrientationChangeEvent which I have my hopes on. I tried it on the mainwindow and on a drawing class derived from qwidget.
But as the name suggests you could very well be right. In which case this event is of no use to me. It seems that widgets really are deprecated.
Back to 5.2 for the last update and bye to qt android.

anda_skoa
23rd August 2014, 15:57
Thanks for your help.
Which event are you talking about? If you mean the QScreenOrientationChangeEvent which I have my hopes on.

Yes.



I tried it on the mainwindow and on a drawing class derived from qwidget.

It might not be sent to windows since it is not related to windows. It affects screens so it is likely sent to screen objects.



But as the name suggests you could very well be right. In which case this event is of no use to me.

How so?


It seems that widgets really are deprecated.

Nope.

Cheers,
_

Cremers
23rd August 2014, 16:21
How so?

Because I need it in a qwidget and qdialog too. For instance I want a dialog to redraw it's stuff when rotation changes.

This was told to me by a fellow qt android dev:

As far as i know and i have been told, widgets are de facto deprecated on qt5/android.


Widgets are still working but there's little work done on them for android. For instance now there's no way to tell an android rotation anymore. Don't get me wrong, I love qt but in case of android you have to go the xml way and not the widget way. Only wish qt would be more clear about it.

anda_skoa
23rd August 2014, 17:54
Because I need it in a qwidget and qdialog too. For instance I want a dialog to redraw it's stuff when rotation changes.

And that is a problem because?



This was told to me by a fellow qt android dev:

I guess most Android devices are phones or tablets, thus better being served by QtQuick, but Qt/Android is not going to remove the widget module or related infrastructure code.



Widgets are still working but there's little work done on them for android. For instance now there's no way to tell an android rotation anymore.

So you are saying that QScreen::orientationChanged() is not emitted?


Don't get me wrong, I love qt but in case of android you have to go the xml way and not the widget way.
You don't have to use XML .ui files to create widget scenes, it is always possible to use C++. Designer is usually just way more convenient.

Cheers,
_

Cremers
23rd August 2014, 18:32
Excuse me for being blunt but I would like to get to the point of this. How do I handle a screen rotation in a qdialog so it can redraw it's stuff? I used to catch this inside QWidget::resizeEvent for the dialog but in 5.3 it doesn't fire anymore, nor for any other qwidget deratives.

anda_skoa
24th August 2014, 09:03
Excuse me for being blunt but I would like to get to the point of this. How do I handle a screen rotation in a qdialog so it can redraw it's stuff?

Qt has a concept called signal&slots.
An "active" object detects some change, e.g. a timer running out, data arriving for a socket, or in this case a screen changing its orientation.
To allow user code to react to that change it emits a signal, basically starting a callback invocation procedure.

Any object, usually a user created one, in your case probably your dialog, has a method called a slot, that can be connected to the sender object's signal.
When the sender emits its signal, all connected receiver slots are invoked.

You will find this pattern a lot in Qt applications, it is quite easy to use.

Cheers,
_

Cremers
24th August 2014, 11:20
Yes I know I can make it work. My point is, it was easy in 5.2 because screenrotation was propageted to the widgets, it's not anymore, functionality for widgets in android is removed in favour of other things.

anda_skoa
24th August 2014, 13:25
Yes I know I can make it work. My point is, it was easy in 5.2 because screenrotation was propageted to the widgets, it's not anymore

Are you sure. In another comment you wrote that you had implemented resizeEvent().



functionality for widgets in android is removed in favour of other things.
The only two classes in QtWidgets, aside from the platform style plugin, with Android specific code are QTextBrowser and QLineEdit.
Neither case has anything to do with orientation change.

On further search there is actually no orientation change occurence in QtWidgets at all, not surprising given that it is already handled at QtGui level.

Cheers,
_

Cremers
24th August 2014, 21:10
Are you sure. In another comment you wrote that you had implemented resizeEvent().

That's in 5.2 yes.


On further search there is actually no orientation change occurence in QtWidgets at all, not surprising given that it is already handled at QtGui level.

In 5.2 there is. The resizeevent can/should be used for the rotation. So my point is, it was relatively easy to get the event but no so anymore.
Widgets on android don't get full support, some can not be used at all in android, it's a well known fact in the necessitas google group, the emphasis is on qtquick.
I have gone back to 5.2, sadly I don't see any future in qt for android with widgets so it'll be an upgrade and then looking for something else. A pity. Really.

anda_skoa
24th August 2014, 21:21
That's in 5.2 yes.

Ok, just verfying that you did not have working code for handling the orientation change event and that no longer works.



In 5.2 there is. The resizeevent can/should be used for the rotation.

So you were relying on an unrelated event being delivered as a side effect of the orientation change.
Have you tried using propery orientation change handling in code compiled against 5.2 and verified that this no longer works in 5.3?


So my point is, it was relatively easy to get the event but no so anymore.

You have confirmed that you did not check for the event, but now you claim you did?
I find that pretty contradictory.

If QScreen does not emit the orientation change signal in Qt5.3 then this is a bug and should be reported.
And it would not be a QtWidget specifc bug since it would affect anything that uses QtGui.

Cheers,
_

d_stranz
24th August 2014, 21:38
In reading this thread, I am puzzled as to how the OP was able to use QResizeEvent to determine that the screen had been rotated. QResizeEvent contains absolutely no screen orientation information at all, just the old and new sizes of the *widget* to which it applies. If the OP was simply making the assumption that the orientation had changed by comparing width and height of the new and old rects, then that is a flawed interpretation of the event.

I think I would be surprised if the resize event was sent at all after an orientation change, because the *widget* has not in fact undergone a change in size.

I also fail to see why a connection can't be made to the QScreen::orientationChanged() signal from anywhere:



QScreen * pScreen = QGuiApplication::primaryScreen();
connect( pScreen, SIGNAL( orientationChanged( int ) ), this, SLOT( onScreenOrientationChanged( int ) ) );

where, of course, you have to write the slot code in your widget class to do whatever is required. Also note this important factoid from the docs:


void QScreen::setOrientationUpdateMask(Qt::ScreenOrient ations mask)

Sets the orientations that the application is interested in receiving updates for in conjunction with this screen.

For example, to receive orientation() updates and thus have orientationChanged() signals being emitted for LandscapeOrientation and InvertedLandscapeOrientation, call setOrientationUpdateMask() with mask set to Qt::LandscapeOrientation | Qt::InvertedLandscapeOrientation.

The default, 0, means no orientationChanged() signals are fired.
(emphasis mine).

If I were to make a guess, if the application sets this flag at the outset, there would be no need to handle orientationChanged() signals at all. The app would probably automatically rotate everything on its own. That the default setting is to ignore orientation changes implies that rotating the screen would have no effect on the app's orientation.

Cremers
25th August 2014, 07:34
In reading this thread, I am puzzled as to how the OP was able to use QResizeEvent to determine that the screen had been rotated.
Be cause that was the way things were done in 5.2 as someone with experience in qt android would know.


If I were to make a guess, if the application sets this flag at the outset, there would be no need to handle orientationChanged() signals at all. The app would probably automatically rotate everything on its own. That the default setting is to ignore orientation changes implies that rotating the screen would have no effect on the app's orientation.

Nice theory. And of course it will also automatically redraw/reposition all stuff to the new resolutions as is needed. Do you know what you are talking about?

anda_skoa
25th August 2014, 16:35
Be cause that was the way things were done in 5.2 as someone with experience in qt android would know.

Are you sure this was documented behavior and not just some incidental side effect?

Cheers,
_

d_stranz
25th August 2014, 18:47
And of course it will also automatically redraw/reposition all stuff to the new resolutions as is needed.
There is no resolution change upon screen rotation. There *is* a change in screen dimension if the screen is rectangular. And yes, if you've used layouts and size hints correctly, Qt is pretty good at automatically repositioning things to fit a new layout size. Of course, if you've made your widgets too big to fit on screen, aren't using layouts, or have set size constraints in such a way that Qt is prevented from doing its thing, then it is entirely possible that you'll see undesirable effects.


Do you know what you are talking about?
Usually.

Cremers
30th August 2014, 12:02
I tried it.


// in constructor
QScreen * screen = QGuiApplication::primaryScreen();
connect(screen, SIGNAL(orientationChanged(Qt::ScreenOrientation)), this, SLOT(onRotate(Qt::ScreenOrientation)));
screen->setOrientationUpdateMask(Qt::PortraitOrientation| Qt::LandscapeOrientation| Qt::InvertedPortraitOrientation| Qt::InvertedLandscapeOrientation);

void MainWindow::onRotate(Qt::ScreenOrientation)
{
QScreen * screen = QGuiApplication::primaryScreen();
QRect r = screen->availableGeometry();
draw(r.height(), r.width());
}


draw(width, height) is my own stuff. Note I had to reverse the order of the parameters in the call, checked with a showMessage() though, that is the correct order, believe me, i didn't believe it myself, i tried the reverse.

Result is: I get correct screensizes, but when I start in portrait, then rotate, I get the correct drawing but the right side of the screen stays black.
Starting in landscape the same, there the lower part stays black after rotate.
It just refuses to paint in the area that wasn't painted in on startup.
Tried several things, checked the onpaint event if it provides the correct sizes, it does, so I'm stuck and back to 5.2.1 for the moment, there it works (via the onresize).

sedi
30th August 2014, 23:56
Hi,
the time when the signal is emitted might be too late in the chain to use it for painting/polishing (i.e. some polishing might be already done).

Two ideas:
- Call the redraw with a QTimer:SingleShot
A few ms will do, this is a quick and dirty thing to get a different thread do the job (the timer thread). Might work.

- Force polishing. I've had a similar problem and that was the solution. I now use

void WhatEverClass::unpolishAll(QObject *object)
{
if (!object)
return;
QWidget* w=dynamic_cast<QWidget *>(object);
if (w) {
w->style()->unpolish(w);
}
foreach (QObject *child, object->children()) {
unpolishAll(child);
}
}
and / or

whatEverObject->ensurePolished();
to force Qt to do its homework.

I'm not sure if this will help here. I am pretty sure though, that I have made some mistakes when trying to explain the workarounds (please correct me!), but they have helped me in similar moments of despair, so it might work for you.

Best regards,
Sebastian