How to determine whether a QML component is currently visible on screen - qt

I have a set of controls which have bindings to frequently changing data values. The data comes from a limited hardware-bus. Therefore, it would be better to disable the binding while the control is not visible on screen. The item's visible-property doesn't help in this case. So, how to determine if an Item-based QML widget is currently visible on screen (and not hidden by an overlay or currently outside the visible area)?
Source: https://forum.qt.io/topic/54116/how-to-check-if-a-item-is-currently-visible-on-screen
I have almost the same problem. Hoping someone here has a solution.

Here's what I would try to get working:
First, I presume there is a ScrollView or Flickable in play here? If so, then hook to signals like Flickable::movementEnded().
Second, when that signal fires, use Item::mapToItem() to check if each of your Item's visible rectangle (based on x, y, width, height) intersects your window's contentItem rectangle. Set the result as a boolean on each of your items and make sure the data retrieval is disabled when it is false (using && or a tertiary JS expression).
Or if more convenient, remove the binding when false and reapply it with Qt.binding() when true.

Related

Why QDeclarativeGeoMap::visibleRegion is non-NOTIFYable in QtLocation Map?

I'm using QtLocation QML Map to display a big amount of items on a map. As with the number of items visible on the map the performance decreases, i would like to set visible only the items actually visible on the viewport. For this it would be handy to just calculate the visibility based on whether the item's coordinate is within the viewport, like:
visible: mapBase.visibleRegion.contains(model.item.coordinate)
But unfortunately the visibleRegion property is non-NOTIFYable, as stated in the documentation at http://doc.qt.io/qt-5/qml-qtlocation-map.html#visibleRegion-prop.
Is there any specific reason (like performance-issues) to not implement a notify signal for this property? Is there any way to workaround this, and set the visibility of a map item based on whether it's within the viewport?
I suppose the reason could be that it's expensive to calculate.
But visibleRegion changes when one of the following properties change: zoomLevel, center, bearing, tilt, fieldOfView. You could, for example, define your own "property var visRegion", and update it when reacting on those properties above by fetching visibleRegion and assigning it to visRegion.

What's the simplest way to get the currently visible rows (first,last) of a QML TableView?

I need to access currently visible rows (first, last) from a JavaScript function, that is defined inside a TableView.
TableView
{
function getVisibleRows()
{
...
}
}
I see that ListView (what is a Flickable) has a contentY property which would make the problem trivial, but TableView has not. Also, TableView is implemented in terms of a ListView, so there is a ListView involved, but I am not sure how to access it.
Thank You!
I've figured out. I simply need to access flickableItem.contentY.
Use the viewport property of Scrollview (inherited by TableView), which
determines the current "window" on the contentItem. In other words, it
clips it and the size of the viewport tells you how much of the
content area is visible.
viewport return a complete qml item so you can get a lot of position data.

Qt Layout, resize to minimum after widget size changes

Basically I've got a QGridLayout with a few widgets in it. The important ones are 2 labels, which I use for drawing images to the screen. Well, if the user wants, he can change the resolution of the incoming images, thus, forcing the Labels to resize.
Let's assume the initial size of the label is 320x240. The user changes the VideoMode to 640x480, the label and the entire GUI resizes perfectly. But when the user switches back to 320x240, the label shrinks, but the Layout/Window does NOT.
I've played around with sizePolicies and sizeHints, and resize(0,0), but nothing did the trick. Could somebody help me with this?
Here some screenshots to clarify the problem:
You need to set the size constraint of the layout holding all your widgets to "SetFixedSize". Although the name doesn't sound like it will work, it ensures that your layout will only use the space it needs. You will not have the problem like you do in your second screenshot.
Example:
mainLayout.setSizeConstraint(QLayout::SetFixedSize);
QLayout::setSizeConstraint(QLayout::SetFixedSize) solves this problem well when you prefer keeping your widget's size fixed at all times--that is, if you'd like it to always be fixed to its "packed" size (which may still vary as the child widgets change size). That is what the "fixed" means there: "fixed" to the correct size, even as the latter varies. (In Qt terms, what I'm calling the "packed" size is simply the widget's sizeHint.)
But a constraint may be too strong a solution in some instances. In particular, if you apply it to a top-level window, then the user will not be free to resize the window. If you don't like that, you can instead perform the "set size to sizeHint" operation instantaneously each time it's needed, rather than imposing it as an unrelenting constraint. The way to do that is to call QWidget::adjustSize().
http://doc.qt.io/qt-5/qwidget.html#adjustSize
Note that if the container whose children are changing size is not the top-level window, then adjustSize() may have to be called recursively on the container and its parents. (In my case I had to do that, anyway. I also tried the size-constraint scheme, and found that applying the constraint at only the topmost level was successful in compacting all levels. I haven't enough knowledge of Qt to comment usefully on these observations, so I merely share them.)
You need to store the original size of your widget parent window before applying any changes to the layout and restore it when the user switches back to the original.
Notice that you need to work with the widget parent window size and not the widget parent size.
in your widget before applying the layout changes:
minimumWindowSize = this->window().size();
when you finished reorganizing the widget to the compact size
this->window().resize(minimumWindowSize);
So that is exactly what i'm doing in mu project.
Resolution os doesn't matter. I have only to have a widget for rendering video, or image in your case.
void MainWindow::resizeEvent(QResizeEvent* event)
{
QMainWindow::resizeEvent(event);
if ((player != 0) && ((player->isPlaying()) || player->isLoaded() || player>isLoaded())){
renderer->resize(ui->mainVideoWidget->width(),ui->mainVideoWidget->height());
resizeFilter();
}
}

InvalidateSize without screen flash?

Here's the scenario: I wait for a creationComplete event to occur for an mx:Text object at which point I can access the setTextFormat method of its protected member textField. (textField is not valid until creationComplete.) At that point the text formatting done through textField.setTextFormat increases the height of the text. But the mx:Text itself does not pick up this height change until I call invalidateSize. However, in my case invalidateSize causes the entire text to be redrawn, causing it to flash on the screen. However, if I just manually change the browser window size, the Text height change is made without the text flashing like that. So how could I through a function call accomplish what is taking place when I manually change the browser window size. (I just want mx:Text to pick up the height change accomplished through textfield.setTextFormat.)
did you tried to put your textfield inside a sprite or movieclip and scale it with your callback?
to invertedspear
I was in fact able to avoid the screen flash by calling
txt1.invalidateSize();
txt1.validateNow();
immediately after the calls to txt1.ui_txtfld().setTextFormat(....)
(ui_txtfld() is how I'm making the protected property textField visible.)
However, elsewhere in my code, it was also necessary to not reference txt1.height directly, but instead,
(txt1.ui_txtfld().textHeight+4)*txt1.scaleY,
as the txt1.textField.textHeight property is valid immediately after changing the height of a textField, whereas txt1.height is not.

Flash/Flex Cursors

I work on a Flex app that loads external Flash resources created in CS3. I've just been reading about how I can use the Flex mx.managers.CursorManager class to change the mouse cursor explicitly. But what I'd ideally like to do is to set a mouse cursor property on some elements in the loaded Flash SWF, so as the cursor passes over this element the cursor automatically changes without me having to respond to mouse events.
Is it possible? Does Flash support this in DisplayObject or something?
It seems the Flash SWF is overriding me. Some objects automatically display the hand cursor with mouse-over, and I can't see a way to turn this off on a DisplayObject?
To set the the "Hand" cursor, as soon as the mouse hovers over a element you have to specify these properties:
<mx:VBox
useHandCursor="true"
mouseChildren="false"
buttonMode="true">
However this only works for the Hand cursor. Also take care of the required mouseChildren attribute. You either have to set this to false to achieve the cursor for all contained items or you have to specify the attributes useHandCursor and buttonMode for all elements. However the side effect of settings mouseChildren to false is that all mouse events (mouseOver, mouseOut, click,...) on child elements will no longer work.
In case you want to use a different cursor than the hand cursor I am afraid you have only two possibilities:
Replace the standard hand cursor by your cursor
Use the mouseOver and mouseOut events to set the cursor programmatically.
In any object inheriting from Sprite whose buttonMode and useHandCursor properties are both true, you'll get a hand cursor by default when you roll over it. Some objects do this by default, correct; Button and LinkButton are examples you've probably noticed. Simply setting useHandCursor to false on any of these components will disable the hand cursor easily enough, even when its buttonMode property (which is responsible for dispatching click events) is set to true.
If you want to set your cursor to anything else on mouseOver, though, you'll have to respond to mouse events; there's no way around that. Depending on your design goal, you could break that work out somehow, maybe by inheriting from some other object and then overriding its default behavior, but in some form or other, the runtime needs to know you want those mouse events handled.

Resources