QT overlapping camera windows issue - qt

We have an overlapping issue on QT Widget windows. 3 camera windows are displayed in our main application. When we zoomed in one of the window, it displays full screen view. However, after approx. 10 minutes, we see other two camera windows on top of zoomed in window (overlapping).
Attaching the screen shot for visualization.
Below is the code snippet for zoom-in and zoom-out functionality.
overlapping camera output
//For making invisible background windows that were coming after zoom in
void MyCamera::zoomInCamera(uint cameraHandle, int camearachanelid)
{
//Start - For continuous clicking
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
GstreamerStream *camHandle=NULL;
if(CAMERA_HANDLE_VALID == isHandleValid(cameraHandle))
{
camHandle = (GstreamerStream*)cameraHandle;
camHandle->zoomInCameraThread();
QWidget *window = camHandle->getWindowObj();
window->setWindowState(window->windowState() ^ Qt::WindowActive);
}
for(int i=0;i<3;i++){
GstreamerStream *camHandleVar = (GstreamerStream*)m_CameraHandles[i];
if( cameraHandle != m_CameraHandles[i] ){
QWidget *window = camHandleVar->getWindowObj();
window->setUpdatesEnabled(false);
//window->hide();
}
}
QApplication::restoreOverrideCursor();
}
//Start - For showing invisible windows after zoom out
void MyCamera::zoomOutCamera(uint cameraHandle, int camearachanelid)
{
//Start - By - For continuous clicking
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
GstreamerStream *camHandle=NULL;
if(CAMERA_HANDLE_VALID == isHandleValid(cameraHandle))
{
camHandle = (GstreamerStream*)cameraHandle;
camHandle->zoomOutCameraThread();
QWidget *window = camHandle->getWindowObj();
window->setWindowState(window->windowState() ^ Qt::WindowActive);
}
for(int i=0;i<3;i++){
GstreamerStream *camHandleVar = (GstreamerStream*)m_CameraHandles[i];
if( cameraHandle != m_CameraHandles[i] ){
QWidget *window = camHandleVar->getWindowObj();
//Added below line
window->setUpdatesEnabled(true);
window->setWindowState(window->windowState() ^ Qt::WindowActive);
}
}
QApplication::restoreOverrideCursor();
}
==========================================================
I tried using setWindowState, setUpdatesEnabled API calls, but it is not working as per expected behaviour.
How do I prevent the windows overlapping issue?
Regards
Amar

Related

Qt5: filtering out the horizontal component from wheel events

I am trying to filter out any horizontal wheel/touchpad scrolling in a widget (ProjectTreeView) that is based on a QTreeView. The idea is to let the vertical movement pass through, supporting horizontal scrolling only via the scrollbar.
I've tried to implement this via a ProjectTreeView::wheelEvent() event handler (below), but that function somehow has the opposite effect. Am I overlooking something (too) obvious or doing something wrong altogether?
void ProjectTreeView::wheelEvent(QWheelEvent *e)
{
if ((e->pixelDelta().x() != 0 || e->angleDelta().x() !=0)
#ifdef Q_OS_MACOS
// allow horizontal scrolling controlled by a physical mouse wheel
&& e->source() != Qt::MouseEventNotSynthesized
#endif
){
QPoint pixelDelta(e->pixelDelta()), angleDelta(e->angleDelta());
// disable horizontal wheel scrolling
pixelDelta.setX(0);
angleDelta.setX(0);
// discard the original event
e->accept();
QWheelEvent filtered(e->posF(), e->globalPosF(), pixelDelta, angleDelta,
e->delta(), e->orientation(), e->buttons(),
e->modifiers(), e->phase(), e->source(), e->inverted());
QCoreApplication::sendEvent(this, &filtered);
} else {
QTreeView::wheelEvent(e);
}
}
When I try to filter via ProjectTreeView::event(QEvent*) I observe that
1) I hardly receive any wheel events at all, at least not when I'm trying to scroll (some come in when I release the touchpad)
2) the events that do come in don't have the required delta information (both components are 0).
This reminds me of remarks I've seen about the Qt4 implementation about how the events are actually treated by a different widget.
thanks!
You can do it easily by installing and event filter function.
bool eventFilter( QObject * o, QEvent * e ) {
if (e->type() == QEvent::Wheel
&& qobject_cast<ProjectTreeView*>( o ) ) {
// Then do what you want, per example: ignore it.
e->ignore();
return true;
}
return QWidget::eventFilter( o, e );
}
If you want the user to use the scroll by clicking in the scrollbar then you can modify the focus polizy of the widget. It should fix your problem:
setFocusPolicy(Qt::ClickFocus);
In the end, this works:
void ProjectTreeView::wheelEvent(QWheelEvent *e)
{
if ((e->pixelDelta().x() !=0 || e->angleDelta().x()!= 0
|| e->orientation() == Qt::Orientation::Horizontal)
#ifdef Q_OS_MACOS
// Cocoa: allow horizontal scrolling controlled by a physical mouse wheel
&& (!isCocoa || e->source() != Qt::MouseEventNotSynthesized)
#endif
){
QPoint pixelDelta(e->pixelDelta()), angleDelta(e->angleDelta());
pixelDelta.setX(0);
angleDelta.setX(0);
// discard the original event
e->ignore();
if (!pixelDelta.isNull() || !angleDelta.isNull()) {
QWheelEvent filtered(e->posF(), e->globalPosF(), pixelDelta, angleDelta,
e->delta(), Qt::Orientation::Vertical, e->buttons(),
e->modifiers(), e->phase(), Qt::MouseEventSynthesizedByApplication, e->inverted());
QCoreApplication::sendEvent(this, &filtered);
}
}
QTreeView::wheelEvent(e);
}
The key was realising that some events only had the orientation set to horizontal but no non-zero delta information.
The isCocoa member is to detect when I'm running my tweaked XCB QPA plugin (= using Qt under XQuartz).

Scaling GraphicsView Widget With Sliders While displaying a Pixmap

I am trying to use the scale(qreal x, qreal y) method/function for Graphics view to scale a pixmap in the graphics view widget. Below I've attached code of my attempts. When I execute the program it will display my pixmap but as soon as I move the horizontal slider the pixmap disappears and the graphics view just displays a blank white page. The commented out parts are all things I have tried but produced the same result. I'm not entirely sure if scaling the graphics view will scale everything in the graphics view, I assumed so but could not find anything concrete from the documentation.
*One thing to note is that I have a button that displays two different Pixmaps, even after I am presented with the white screen upon moving the scroll bar, if I press the button it will still update the y axis scroll bar(as one pixmap is slightly larger than the graphics widget) however a blank white graphics view is still displayed
*PixMapView is the name of the graphics view widget
void CanvasTest::on_horizontalSlider_valueChanged(int value)
{
//int scaleX = value/(ui->horizontalSlider->maximum())*2;
//Graph is updating and Y scroll bar is updating to show for it
//int scaleY = ui->verticalSlider->value();
QGraphicsScene* scene = ui->PixMapView->scene();
ui->PixMapView->scale(value/10, 1);
ui->PixMapView->setScene(scene);
ui->PixMapView->show();
}
There was truncation issue using integers, this code also uses static variables to keep track of the previous scale values.
static float valueTracker = 1;\
static float valueTracker1 = 1;
static int count = 1;
bool order;
if (count%2 == 1)
{
valueTracker = newSliderValue;
order = 0;
}
else
{
valueTracker1 = newSliderValue;
order = 1;
}
if(valueTracker == valueTracker1 || valueTracker == 0 || valueTracker1 == 0)
{
count++;
return;
}
else if(order == 0)
{
ui->PixMapView->scale(((valueTracker/valueTracker1)), 1);
}
else if(order == 1)
{
ui->PixMapView->scale(((valueTracker1/valueTracker)), 1);
}
count++;

How to scale the contents of a QGraphicsView using the QPinchGesture?

I'm implementing an image viewer on an embedded platform. The hardware is a sort of tablet and has a touch screen as input device. The Qt version I'm using is 5.4.3.
The QGraphicsView is used to display a QGraphicsScene which contains a QGraphicsPixmapItem. The QGraphicsPixmapItem containts the pixmap to display.
The relevant part of the code is the following:
void MyGraphicsView::pinchTriggered(QPinchGesture *gesture)
{
QPinchGesture::ChangeFlags changeFlags = gesture->changeFlags();
if (changeFlags & QPinchGesture::ScaleFactorChanged) {
currentStepScaleFactor = gesture->totalScaleFactor();
}
if (gesture->state() == Qt::GestureFinished) {
scaleFactor *= currentStepScaleFactor;
currentStepScaleFactor = 1;
return;
}
// Compute the scale factor based on the current pinch level
qreal sxy = scaleFactor * currentStepScaleFactor;
// Get the pointer to the currently displayed picture
QList<QGraphicsItem *> listOfItems = items();
QGraphicsItem* item = listOfItems.at(0);
// Scale the picture
item.setScale(sxy);
// Adapt the scene to the scaled picture
setSceneRect(scene()->itemsBoundingRect());
}
As result of the pinch, the pixmap is scaled starting from the top-left corner of the view.
How to scale the pixmap respect to the center of the QPinchGesture?
From The Docs
The item is scaled around its transform origin point, which by default is (0, 0). You can select a different transformation origin by calling setTransformOriginPoint().
That function takes in a QPoint so you would need to find out your centre point first then set the origin point.
void QGraphicsItem::setTransformOriginPoint(const QPointF & origin)

Dragged QGraphicsItem not visible in items() function

I have created a QGraphicsScene scene and added some graphcis items (lines, rectangles) etc to the scene.
I can loop through them using this list :
QList<QGraphicsItem*> all = items();
I enabled movement for these items and I am able to drag them by click selecting them. But after an element has been dragged, it stops showing up in the call to items() function of the QGraphicsScene.
QList<QGraphicsItem*> all = items();
None of the dragged items show up in the above list, while non-dragged ones do show up.
Does dragging the QGraphicScene elements change their parent ? or any other reason somebody could suggest for such an issue ?
{P.S. Code is too very big to share}
Edit 1 :
I am using the flags QGraphicsItem::ItemIsSelectable and QGraphicsItem::ItemIsMovable for making the items movable.
foreach(QGraphicsItem* itemInVisualScene, items())
{
itemInVisualScene->setFlag(QGraphicsItem::ItemIsSelectable, itemsMovable);
itemInVisualScene->setFlag(QGraphicsItem::ItemIsMovable, itemsMovable);
}
By default I add few rectangle to the scene. Then in the 'move mode' I drag them around. Then in the 'add mode' I click on screen to add new rectangles. I have written a logic to check if I am clicking on any existing drawn rectangle :
void Scene::mousePressEvent(QGraphicsSceneMouseEvent * event)
{
if(eDrawLines == sceneMode)
{
dragBeginPoint = event->scenePos();
dragEndPoint = dragBeginPoint;
QList<QGraphicsItem*> all = items();
for (int i = 0; i < all.size(); i++)
{
QGraphicsItem *gi = all[i];
// Clicked point lies inside existing rect
if( QGraphicsRectItem::Type == gi->type() && gi->contains(dragBeginPoint))
{
std::cout << "Pressed inside existing rect" << std::endl;
return;
}
}
std::cout << "Point not found, add new rectangle" << std::endl;
}
QGraphicsScene::mousePressEvent(event);
}
This adding of rectangles work fine for rects which were not dragged in the 'move mode'. But rects which were moved do not seem to recognize the click anymore. My control comes out of the loop even when I click on an existing rectangle which was dragged earlier.
QGraphicsItem's transform is changed after dragging and therefore need to transform the point to item's local coordinates.
gi->contains(gi->mapFromScene(dragBeginPoint))
To convert or get item's position in scene coordinates, use
gi->mapToScene(0,0) or gi->scenePos()

Displaying image as background of QGraphicsScene

I try to use QGraphicsView to display a map with some QGraphicItem-subclass showing region centers of the map. Conceptually, I organize the map as follow:
QGraphicsView
QGraphicsScene
QGraphicsPixmapItem : background image, fixed until next call of loadSetting
QGraphicsRectItem : legend, position relative to bg is fixed throughout app
QGraphicsEllipseItem : region centers
I want the map to behave as follow:
no scrollbars to be displayed, and the background image fillup all the visible area of the view/scene.
when the widget is re-sized, the QGraphics*Items will re-size themselves accordingly (as if the view is zoomed)
relative positions of QGraphicsEllipseItems, remain fixed until next call of loadSetting()
Now I have problem in getting the background image displayed properly.
Constructor [I'm adding this view to a QTabWidget directly: myTab->addTab("name", my_view_); ]
MyView::MyView(QWidget *parent) : QGraphicsView(parent) {
bg_pixmap_ = new QGraphicsPixmapItem();
legend_ = new MapLegend();
setScene(new QGraphicsScene(this));
scene()->addItem(bg_pixmap_);
scene()->addItem(legend_);
}
Load map setting (during program execution, this method may be invoked multiple times)
void MyView::loadSetting(Config* cfg) {
if (!cfg) return;
/* (a) */
scene()->clearFocus();
scene()->clearSelection();
for (int i = 0; i < symbols_.size(); i++)
scene()->removeItem(symbols_[i]);
qDeleteAll(symbols_);
symbols_.clear();
/* (a) */
/* (b) */
background_ = QPixmap(QString::fromStdString(cfg->district_map));
bg_pixmap_->setPixmap(background_);
for (size_t i = 0; i < cfg->centers.size(); i++) {
qreal x = cfg->centers[i].first * background_.width();
qreal y = cfg->centers[i].second * background_.height();
MapSymbol* item = new MapSymbol(x, y, 10);
symbols_.append(item);
scene()->addItem(item);
}
/* (b) */
update();
}
Questions
Now all items except the 'bg_pixmap_' got displayed, and I checked the 'background_' variable that it loads the image correctly. Is there anything I missed?
How do I implement the resizeEvent of MyView to cope with the desired 'resize-strategy'?

Resources