Mouse events blocked because of QGL View - qt

I created a simple project to show the problem I have in a bigger application.
So, I create a mainwindow with 2 buttons. I create a class which inherit from QWidget with 2 buttons and a QGL view.
The problem is that, apparently and for some reason I don't find, the creation of this QGL view blocks some events of the views, particularly mouse events. In the code below, the mouse hover events on the buttons and the main widget of class 1 are not detected (the cursor has to change from Arrow to hand and wait respectively) whereas the mouse cursor changes well on the mainwindow buttons (but in my real application, it's more serious than a simple hover event).
I precise that this problem appears only on Mac 10.6 and superior, and not on Windows. I use Qt 5.1.
Here is the code :
mainwindow.h :
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class Class1;
class PanoramaGLView;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
Class1 *c1;
PanoramaGLView *gl;
};
#endif // MAINWINDOW_H
mainwindoww.cpp :
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
using namespace std;
#include "class1.h"
#include "panoramaglview.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
c1=new Class1(0);
ui->centralLayout->addWidget(c1);
//if created here, no problem with mouse cursor on mainwindow buttons but not what I want
//gl=new PanoramaGLView(0);
//ui->centralLayout->addWidget(gl);
}
MainWindow::~MainWindow()
{
delete ui;
}
myglview.h :
#ifndef MYGLVIEW_H
#define MYGLVIEW_H
#include <QGraphicsView>
#include <QtOpenGL/QGLWidget>
class MyGLView : public QGraphicsView
{
Q_OBJECT
public:
MyGLView(QWidget* pParent = 0);
virtual ~MyGLView();
protected:
QGLWidget* m_pGLWidget;
};
#endif // MYGLVIEW_H
myglview.cpp :
#include "myglview.h"
MyGLView::MyGLView(QWidget* pParent)
: QGraphicsView(pParent)
{
m_pGLWidget = new QGLWidget(QGLFormat(QGL::SampleBuffers | QGL::AlphaChannel));
m_pGLWidget->makeCurrent();
setViewport(m_pGLWidget);
setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
}
MyGLView::~MyGLView()
{
delete m_pGLWidget;
}
class1.h :
#ifndef CLASS1_H
#define CLASS1_H
#include <QWidget>
class MyGLView;
namespace Ui {
class Class1;
}
class Class1 : public QWidget
{
Q_OBJECT
public:
explicit Class1(QWidget *parent = 0);
~Class1();
private:
Ui::Class1 *ui;
public slots:
void click1();
};
#endif // CLASS1_H
class1.cpp :
#include "class1.h"
#include "ui_class1.h"
#include "myglview.h"
#include <iostream>
using namespace std;
Class1::Class1(QWidget *parent) :
QWidget(parent),
ui(new Ui::Class1)
{
ui->setupUi(this);
MyGLView *glv=new MyGLView(0);
ui->verticalLayout->addWidget(glv);
connect(ui->pushButton,SIGNAL(clicked()),this,SLOT(click1()));
}
Class1::~Class1()
{
delete ui;
}
void Class1::click1(){
cout<<"Class1::click1()"<<endl;
}
mainwindow.ui :
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="centralLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<property name="styleSheet">
<string notr="true">background-color: rgb(255, 54, 76);</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="pushButton">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
class1.ui :
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Class1</class>
<widget class="QWidget" name="Class1">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="cursor">
<cursorShape>WaitCursor</cursorShape>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="pushButton">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string>1</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_2">
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text">
<string>2</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
If I don't create the GL view, there is no problem of course. And if I create the myGLView instance directly in MainWindow, without class1, it works too. But I need to create différents views and not all in mainwindow (which is usually how ui are created).
In my opinion, it's a problem with the way I create the view, its parent or something like that, as event are passed from parent to child, so I think the problem has a link with that. If it works well, the mouse cursor has to change when the mouse passes over the buttons 1 and 2 (hand cursor) and just hover class1 main widget (waiting cursor).
Any ideas?

I can confirm that this is a regression. Tested on OS X 10.8.4. It works under Qt 4.8.5, doesn't work under Qt 5.1.0. You should report it as a bug. Below is a sane single-file test case that you will know to produce the next time you post to stackoverflow :)
//main.cpp
#include <QApplication>
#include <QPushButton>
#include <QStackedWidget>
#include <QVBoxLayout>
#include <QGraphicsView>
#include <QGLWidget>
class TestView : public QGraphicsView
{
public:
explicit TestView(QWidget* parent = 0) : QGraphicsView(parent) {
setViewport(new QGLWidget());
setScene(new QGraphicsScene(this));
scene()->addEllipse(-50, -50, 100, 100, QPen(Qt::red), QBrush(Qt::lightGray));
}
};
class Pane : public QWidget
{
public:
explicit Pane(bool hasView, const QCursor & cur, QWidget *parent = 0) :
QWidget(parent)
{
QVBoxLayout * l = new QVBoxLayout(this);
QPushButton * btn = new QPushButton("[Pane]");
btn->setCursor(cur);
l->addWidget(btn);
if (hasView) l->addWidget(new TestView()); else l->addStretch();
}
};
class MainWindow : public QWidget
{
Q_OBJECT
QStackedWidget *sw;
public:
explicit MainWindow(QWidget *parent = 0) : QWidget(parent) {
QVBoxLayout *l = new QVBoxLayout(this);
QPushButton *btn = new QPushButton("[Main Window] Flip Pages");
btn->setCursor(Qt::PointingHandCursor);
connect(btn, SIGNAL(clicked()), SLOT(nextPage()));
sw = new QStackedWidget();
l->addWidget(btn);
l->addWidget(sw);
sw->addWidget(new Pane(true, Qt::OpenHandCursor));
sw->addWidget(new Pane(false, Qt::ClosedHandCursor));
}
Q_SLOT void nextPage() { sw->setCurrentIndex((sw->currentIndex() + 1) % sw->count()); }
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
#include "main.moc"

Related

Increase in memory usage for QObject::connect call

We are facing issue related to increase in memory usage due to
QObject::connect call in our application. This is causing an application crash
after continuous execution for 16~17 Hrs. Here we are trying to understand the
reason for increase in memory usage due to QObject::connect call and if there
is any specific way to handle the same.
To simulate the same I created a sample application, which is performing the following (Please refer to
the app screenshot for better understanding):
On press of "Start" button, the application will start creating
objects pointers of a class at an interval of 50 ms in a separate
thread. Each object pointer of the class will create a buffer of
1000 bytes internally. And the new pointer will be stored in a list
(which is a member variable of the object creation thread). On every
new object creation the same will be notified to the MainWindow (the
ui thread), with the created object pointer.
On notified by the object creation thread, the MainWindow can
perform following 2 actions depending on the "Use Connect" check box
status:
a. Initialize a local member variable to the new object
created.
b. disconnect/connect to the destroyed() signal of the new
object created to a slot, if "Use Connect" check box is checked.
Observation:
We ran the sample application for 5 minutes and collected the result for
both "with connect" and "without connect" method call.
collected 5 samples for both the condition.
The memory usage for "Without connect" call comes around 8.5 Mb
(almost constant for all 5 samples collected)
The memory usage for "With connect call" comes around 9.7 Mb
(almost constant for all 5 samples collected)
Above result suggests that, when connect call happens memory usage is
increasing. And this is what is aso observed in out actual project.
We are trying to understand the reason for additional memory usage in case of
"With connect" call and need a solution/suggestion for the same.
Kindly let us know your input on the same.
Main.cpp
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
HeavyClass.cpp
#include "HeavyClass.h"
#include <QDateTime>
const unsigned int CHeaveyClass::kArraySize = 1000;
CHeaveyClass::CHeaveyClass(QObject *parent)
: QObject(parent)
, m_pForMemAllocaion(nullptr)
{
m_pForMemAllocaion = new char[kArraySize];
if (m_pForMemAllocaion)
{
memset(m_pForMemAllocaion, 0, kArraySize);
sprintf_s(m_pForMemAllocaion, kArraySize, "I am created at Bikash %s", QDateTime::currentDateTime().toString().toStdString().c_str());
}
}
CHeaveyClass::~CHeaveyClass()
{
if (m_pForMemAllocaion)
{
delete m_pForMemAllocaion;
m_pForMemAllocaion = nullptr;
}
}
HeaveyClass.h
#ifndef CHEAVYCLASS_H
#define CHEAVYCLASS_H
#include <QObject>
class CHeaveyClass : public QObject
{
Q_OBJECT
public:
explicit CHeaveyClass(QObject *parent = nullptr);
~CHeaveyClass();
signals:
private:
char* m_pForMemAllocaion;
const static unsigned int kArraySize;
};
#endif // CHEAVYCLASS_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "MyThread.h"
#include "HeavyClass.h"
#include <QTimer>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
, m_pHeaveyClass(nullptr)
, m_pTimer(nullptr)
{
ui->setupUi(this);
ui->clearMemoryButton->setEnabled(false);
m_pMyThread = new CMyThread(nullptr, this);
if (m_pMyThread)
{
connect(m_pMyThread, SIGNAL(listSizeChanged(unsigned int)), this, SLOT(OnListSizeChanged(unsigned int)));
}
m_pTimer = new QTimer();
if (m_pTimer)
{
connect(m_pTimer, SIGNAL(timeout()), this, SLOT(OnTimerTimeOut()));
}
}
MainWindow::~MainWindow()
{
if (m_pMyThread)
{
disconnect(m_pMyThread, SIGNAL(listSizeChanged(unsigned int)), this, SLOT(OnListSizeChanged(unsigned int)));
delete m_pMyThread;
m_pMyThread = nullptr;
}
if (m_pTimer)
{
if (m_pTimer->isActive())
{
m_pTimer->stop();
}
disconnect(m_pTimer, SIGNAL(timeout()), this, SLOT(OnTimerTimeOut()));
delete m_pTimer;
m_pTimer = nullptr;
}
delete ui;
}
void MainWindow::on_startButton_clicked()
{
if (0 == ui->startButton->text().compare("start", Qt::CaseInsensitive))
{
ui->startButton->setText("Stop");
ui->clearMemoryButton->setEnabled(false);
if (m_pMyThread)
{
m_pMyThread->start();
}
if (m_pTimer)
{
m_tStartTime = QTime::currentTime();
m_pTimer->start(1000);
}
}
else
{
ui->startButton->setText("Start");
ui->timeLabel->clear();
ui->ranFor->clear();
if (m_pMyThread)
{
m_pMyThread->StopThread();
}
if (m_pTimer)
{
m_pTimer->stop();
}
}
}
void MainWindow::OnListSizeChanged(unsigned int size)
{
ui->clearMemoryButton->setEnabled(size > 0 ? true : false);
}
void MainWindow::setPrefferedHeavyObject(CHeaveyClass *ptr)
{
Q_UNUSED(ptr)
if (ui->useConnect->checkState() == Qt::Checked)
disconnect(m_pHeaveyClass,SIGNAL(destroyed(QObject*)));
m_pHeaveyClass = ptr;
if (ui->useConnect->checkState() == Qt::Checked)
connect(m_pHeaveyClass, SIGNAL(destroyed(QObject*)), this, SLOT(OnPrefferedHeavyObjectDeleted(QObject*)));
}
void MainWindow::on_clearMemoryButton_clicked()
{
m_pMyThread->ClearMemory();
}
void MainWindow::OnPrefferedHeavyObjectDeleted(QObject *ptr)
{
Q_UNUSED(ptr)
m_pHeaveyClass = nullptr;
}
void MainWindow::OnTimerTimeOut()
{
QTime currentTime = QTime::currentTime();
ui->timeLabel->setText("Current Time : " + currentTime.toString());
int timeDiffInSecs = m_tStartTime.secsTo(currentTime);
ui->ranFor->setText("Ran for : " + QString::number(timeDiffInSecs) + " secs");
if (timeDiffInSecs == 300)
{
on_startButton_clicked();
}
}
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "IMainWindow.h"
#include <QTime>
class CHeaveyClass;
class CMyThread;
class QTimer;
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow
: public QMainWindow
, public IMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_startButton_clicked();
void OnListSizeChanged(unsigned int size);
void on_clearMemoryButton_clicked();
void OnPrefferedHeavyObjectDeleted(QObject* ptr);
void OnTimerTimeOut();
// IMainWindow interface
protected:
void setPrefferedHeavyObject(CHeaveyClass *ptr);
private:
Ui::MainWindow *ui;
CHeaveyClass* m_pHeaveyClass;
CMyThread* m_pMyThread;
QTimer* m_pTimer;
QTime m_tStartTime;
};
#endif // MAINWINDOW_H
MyThread.cpp
#include "MyThread.h"
#include "HeavyClass.h"
#include <QDebug>
#include "IMainWindow.h"
CMyThread::CMyThread(QObject *pParent, IMainWindow* pMainWindowInterface)
: QThread(pParent)
, m_pMainWindow(pMainWindowInterface)
{
m_lstHeavyClass.clear();
}
CMyThread::~CMyThread()
{
StopThread();
while (isRunning());
ClearMemory();
qDebug() << "Destroying the thread.";
}
void CMyThread::StopThread()
{
m_bContinueExecution = false;
}
void CMyThread::ClearMemory()
{
if (false == isRunning())
{
while (m_lstHeavyClass.size() != 0)
{
CHeaveyClass* p = m_lstHeavyClass.last();
m_lstHeavyClass.removeLast();
delete p;
p = nullptr;
listSizeChanged(m_lstHeavyClass.size());
}
qDebug() << "All created heavy class ptrs are deleted.";
}
else
{
qDebug() << "Thread is still active. Stop the thread first.";
}
}
void CMyThread::run()
{
m_bContinueExecution = true;
while (m_bContinueExecution)
{
CHeaveyClass * pHeavyClass = new CHeaveyClass();
if (pHeavyClass)
{
m_lstHeavyClass.append(pHeavyClass);
m_pMainWindow->setPrefferedHeavyObject(pHeavyClass);
listSizeChanged(m_lstHeavyClass.size());
msleep(50);
}
}
qDebug() << "Stopping thread execution.";
}
MyThread.h
#ifndef CMYTHREAD_H
#define CMYTHREAD_H
#include <QThread>
class IMainWindow;
class CHeaveyClass;
class CMyThread : public QThread
{
Q_OBJECT
public:
explicit CMyThread(QObject* pParent = nullptr, IMainWindow* pMainWindowInterface = nullptr);
~CMyThread();
void StopThread();
void ClearMemory();
// QThread interface
signals:
void listSizeChanged(unsigned int size);
protected:
void run();
private:
bool m_bContinueExecution;
IMainWindow* m_pMainWindow;
QList<CHeaveyClass*> m_lstHeavyClass;
};
#endif // CMYTHREAD_H
IMainWindow.h
#ifndef IMAINWINDOW_H
#define IMAINWINDOW_H
class CHeaveyClass;
class IMainWindow {
public:
virtual void setPrefferedHeavyObject(CHeaveyClass* ptr) = 0;
};
#endif // IMAINWINDOW_H
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>400</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QPushButton" name="startButton">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="useConnect">
<property name="text">
<string>Use Connect</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="clearMemoryButton">
<property name="text">
<string>Clear Memory</string>
</property>
</widget>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="timeLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="ranFor">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>26</height>
</rect>
</property>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>
</ui>

How to create a transparent QWidget on top of a sibling QVideoWidget?

I want to add some controls and information on top of a fullscreen QVideoWidget. So I create a QMainWindow ui and then promote the central widget to QVideoWidget as:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>VideoScreen</class>
<widget class="QMainWindow" name="VideoScreen">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<widget class="QVideoWidget" name="videoScreen">
<property name="styleSheet">
<string notr="true"/>
</property>
</widget>
</widget>
<customwidgets>
<customwidget>
<class>QVideoWidget</class>
<extends>QWidget</extends>
<header>QVideoWidget</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
And ControlBoards ui:
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ControlBoard</class>
<widget class="QWidget" name="ControlBoard">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1044</width>
<height>520</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<widget class="QLabel" name="title">
<property name="geometry">
<rect>
<x>210</x>
<y>90</y>
<width>59</width>
<height>17</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true">
</string>
</property>
<property name="text">
<string>Title</string>
</property>
</widget>
<widget class="QPushButton" name="play">
<property name="geometry">
<rect>
<x>320</x>
<y>120</y>
<width>101</width>
<height>31</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>play</string>
</property>
</widget>
<widget class="QPushButton" name="stop">
<property name="geometry">
<rect>
<x>210</x>
<y>120</y>
<width>101</width>
<height>31</height>
</rect>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="text">
<string>stop</string>
</property>
</widget>
</widget>
<resources/>
<connections/>
</ui>
Then in videoscreen.cpp, I also add the ControlBoard as sibling of QVideoWidget:
VideoScreen::VideoScreen(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::VideoScreen), player(new QMediaPlayer)
{
ui->setupUi(this);
player->setVideoOutput(ui->videoScreen);
ui->videoScreen->lower();
ControlBoard *cb = new ControlBoard(this);
}
When I play a video, the result:
How to make the ControlBoard be transparent so that we can see the video behind?
I tried some code in ControlBoard constructor:
// setWindowFlags(Qt::Widget | Qt::FramelessWindowHint);
// setAttribute(Qt::WA_NoSystemBackground);
// setAttribute(Qt::WA_TranslucentBackground);
// setAttribute(Qt::WA_PaintOnScreen);
// setAttribute(Qt::WA_TransparentForMouseEvents);
// setAutoFillBackground(false);
But this just show the parent's background, not the sibling video. Does Qt5 support this? Thanks!
UPDATE:
I also tried on some other like this (base on):
class OverlayWidget : public QWidget
{
void newParent() {
if (!parent()) return;
parent()->installEventFilter(this);
raise();
}
public:
explicit OverlayWidget(QWidget * parent = {}) : QWidget{parent} {
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TransparentForMouseEvents);
newParent();
}
protected:
//! Catches resize and child events from the parent widget
bool eventFilter(QObject * obj, QEvent * ev) override {
if (obj == parent()) {
if (ev->type() == QEvent::Resize)
{
// resize(static_cast<QResizeEvent*>(ev)->size());
}
else if (ev->type() == QEvent::ChildAdded)
raise();
}
return QWidget::eventFilter(obj, ev);
}
//! Tracks parent widget changes
bool event(QEvent* ev) override {
if (ev->type() == QEvent::ParentAboutToChange) {
if (parent()) parent()->removeEventFilter(this);
}
else if (ev->type() == QEvent::ParentChange)
newParent();
return QWidget::event(ev);
}
};
class LoadingOverlay : public OverlayWidget
{
public:
LoadingOverlay(QWidget * parent = {}) : OverlayWidget{parent} {
setAttribute(Qt::WA_TranslucentBackground);
}
protected:
void paintEvent(QPaintEvent *) override {
QPainter p(this);
// p.fillRect(rect(), {10, 10, 10, 100});
p.setPen({200, 200, 255});
p.setFont({"arial,helvetica", 48});
p.drawText(rect(), "Loading...", Qt::AlignHCenter | Qt::AlignVCenter);
}
};
int main(int argc, char * argv[])
{
QApplication a(argc, argv);
QMainWindow window;
QVideoWidget central(&window);
central.setMinimumSize(600, 700);
window.setCentralWidget(&central);
QMediaPlayer player;
player.setMedia(QUrl::fromLocalFile("dolbycanyon.mov"));
player.setVideoOutput(&central);
LoadingOverlay overlay(&window);
overlay.resize(400, 300);
overlay.setWindowOpacity(.4);
overlay.setWindowFlags(Qt::Widget | Qt::FramelessWindowHint);
overlay.setAttribute(Qt::WA_PaintOnScreen);
overlay.setAutoFillBackground(false);
// QTimer::singleShot(5000, &overlay, SLOT(hide()));
// QTimer::singleShot(7000, &player, SLOT(play()));
player.play();
window.show();
return a.exec();
}
But the result is still opaque, not transparent:
Demo of transparent background overlay on the video:
#include <QApplication>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QGraphicsVideoItem>
#include <QMediaPlayer>
#include <QFileDialog>
#include <QPushButton>
#include <QLabel>
#include <QGraphicsProxyWidget>
const QSizeF VideoItemSize(500, 500);
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMediaPlayer player;
QGraphicsView v;
QGraphicsScene scene;
QGraphicsVideoItem video;
v.setScene(&scene);
video.setSize(VideoItemSize);
scene.setSceneRect(QRectF(QPointF(0, 0), VideoItemSize)); // VideoItem full fill the scene
scene.addItem(&video);
player.setVideoOutput(&video);
player.setMedia(QMediaContent(QFileDialog::getOpenFileUrl()));
// Recommend using QGraphicsItems for overlay component
QGraphicsTextItem text("Loading...",&video);
text.setPos(100, 150);
// If you need a button...
QPushButton button("ButtonTest");
QGraphicsProxyWidget* proxyButton = scene.addWidget(&button);
proxyButton->setPos(100, 200);
// Instead of QGraphicsItems, if you really need a QWidget...
QLabel label("LabelTest");
label.setAttribute(Qt::WA_TranslucentBackground); // You can delete this line to see different
QGraphicsProxyWidget* proxyLabel = scene.addWidget(&label);
proxyLabel->setPos(100, 250);
v.show();
player.play();
return a.exec();
}

qt memory issue QTable widget

I have installed Qt Creator and created a project which will show huge amount of data in a QTableWidget. I have some issue with the memory usage. My project using ~2 GB of RAM when its showing table data. There are nearly 1.4 million rows and each row has 8 columns.
How to solve this issue? Whether the procedure which I used for creating table is wrong?
My code:
main.cpp :
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp :
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
t1 = new QTableWidgetItem();
t2 = new QTableWidgetItem();
t3 = new QTableWidgetItem();
t4 = new QTableWidgetItem();
t5 = new QTableWidgetItem();
t6 = new QTableWidgetItem();
t7 = new QTableWidgetItem();
t8 = new QTableWidgetItem();
qDebug()<<sizeof(t1);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
delete t1;
delete t2;
delete t3;
delete t4;
delete t5;
delete t6;
delete t7;
delete t8;
unsigned int index =0;
ui->tableWidget->setRowCount(1426500);
while (index < 1426500)
{
t1 = new QTableWidgetItem();
t1->setText(QString::number(index));
ui->tableWidget->setItem(index,0,t1);
ui->tableWidget->item(index,0)->setBackgroundColor(QColor(180,150,220));
t2 = new QTableWidgetItem();
t2->setText(QString::number(index));
ui->tableWidget->setItem(index,1,t2);
ui->tableWidget->item(index,1)->setBackgroundColor(QColor(180,150,220));
t3 = new QTableWidgetItem();
t3->setText(QString::number(index));
ui->tableWidget->setItem(index,2,t3);
ui->tableWidget->item(index,2)->setBackgroundColor(QColor(180,150,220));
t4 = new QTableWidgetItem();
t4->setText(QString::number(index));
ui->tableWidget->setItem(index,3,t4);
ui->tableWidget->item(index,3)->setBackgroundColor(QColor(180,150,220));
t5 = new QTableWidgetItem();
t5->setText(QString::number(index));
ui->tableWidget->setItem(index,4,t5);
ui->tableWidget->item(index,4)->setBackgroundColor(QColor(180,150,220));
t6 = new QTableWidgetItem();
t6->setText(QString::number(index));
ui->tableWidget->setItem(index,5,t6);
ui->tableWidget->item(index,5)->setBackgroundColor(QColor(180,150,220));
t7 = new QTableWidgetItem();
t7->setText(QString::number(index));
ui->tableWidget->setItem(index,6,t7);
ui->tableWidget->item(index,6)->setBackgroundColor(QColor(180,150,220));
t8 = new QTableWidgetItem();
t8->setText(QString::number(index));
ui->tableWidget->setItem(index,7,t8);
ui->tableWidget->item(index,7)->setBackgroundColor(QColor(180,150,220));
index++;
}
}
mainwindow.h :
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QTableWidgetItem>
#include <QDebug>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QTableWidgetItem *t1;
QTableWidgetItem *t2;
QTableWidgetItem *t3;
QTableWidgetItem *t4;
QTableWidgetItem *t5;
QTableWidgetItem *t6;
QTableWidgetItem *t7;
QTableWidgetItem *t8;
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.ui :
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1122</width>
<height>572</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>10</x>
<y>0</y>
<width>99</width>
<height>27</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
<widget class="QTableWidget" name="tableWidget">
<property name="geometry">
<rect>
<x>40</x>
<y>50</y>
<width>1031</width>
<height>441</height>
</rect>
</property>
<property name="columnCount">
<number>8</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<column/>
<column/>
<column/>
<column/>
<column/>
<column/>
<column/>
<column/>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1122</width>
<height>25</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
QTableTest.pro :
#-------------------------------------------------
#
# Project created by QtCreator 2017-08-12T12:22:34
#
#-------------------------------------------------
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = QTableTest
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui

OpenFileDialog in a dynamic QDialog

I am trying to build a form with several LineEdits and I need an OpenFileDialog to select a Path and write it into one of the LineEdits.
The problem is, this form is generated "dynamically".
All of this needs to happen inside a function call, in which the Dialog and all LineEdits are created, so i can't just add a Button, link the clicked Signal to a new Slot, open the File Dialog in the Slot and write the result into the LineEdit.
Here is my Code from inside the function:
QDialog dialog(this);
QFormLayout form(&dialog);
QList<QLineEdit *> fields;
QLineEdit *lineEdit = new QLineEdit(&dialog);
QString label = QString("Name");
form.addRow(label, lineEdit);
fields << lineEdit;
lineEdit = new QLineEdit(&dialog);
label = QString("Time");
form.addRow(label, lineEdit);
fields << lineEdit;
lineEdit = new QLineEdit(&dialog);
label = QString("Number #1");
form.addRow(label, lineEdit);
fields << lineEdit;
lineEdit = new QLineEdit(&dialog);
label = QString("Number #2");
form.addRow(label, lineEdit);
fields << lineEdit;
lineEdit = new QLineEdit(&dialog);
label = QString("Number #3");
form.addRow(label, lineEdit);
fields << lineEdit;
//--------------Here should be the path selection
lineEdit = new QLineEdit(&dialog);
label = QString("Path");
form.addRow(label, lineEdit);
fields << lineEdit;
//-----------------------------------------------
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,Qt::Horizontal, &dialog);
form.addRow(&buttonBox);
QObject::connect(&buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()));
QObject::connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()));
if (dialog.exec() == QDialog::Accepted) {
//...Do stuff with the Text from the Line Edits
Is there a way to do this without making things global, so a Slot could access it?
Because I really like the idea of this form completely staying inside the function call.
If I understood the issue correctly, I think you need to redesign the application.
You need some variables in your class and update the dialog when the user changes the QLineEdit path. But to do this, you need the dialog as a member variable.
The next code is just an example, but it's a good way of showing you a way of solving this. Of course, there are many different options to do it.
Note #1: I don't know when you launch the dialog, so I've created a very basic ui with a button to display it.
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>160</x>
<y>120</y>
<width>75</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>PushButton</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>21</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QLineEdit>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void updateValues(const QString & text);
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QLineEdit* path;
QLineEdit* name;
QLineEdit* time;
QLineEdit* number;
QDialog* dialog;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QLineEdit>
#include <QDialogButtonBox>
#include <QFormLayout>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
dialog = new QDialog(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QFormLayout form(dialog);
name = new QLineEdit(dialog);
QString label = QString("Name");
form.addRow(label, name);
time = new QLineEdit(dialog);
label = QString("Time");
form.addRow(label, time);
number = new QLineEdit(dialog);
label = QString("Number #1");
form.addRow(label, number);
path = new QLineEdit(dialog);
label = QString("Path");
form.addRow(label, path);
connect(path, &QLineEdit::textChanged,
this, &MainWindow::updateValues );
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel,Qt::Horizontal, dialog);
form.addRow(&buttonBox);
QObject::connect(&buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
QObject::connect(&buttonBox, SIGNAL(rejected()), dialog, SLOT(reject()));
dialog->exec();
}
void MainWindow::updateValues(const QString & text)
{
name->setText(text);
time->setText(text);
number->setText(text);
}

Qt Creator: Design changes not showing when run

I had made some changes on the 'mainwindow.ui' file from the folder: 'Forms'.
I've added a new title entitled 'File' and there only two simple options, 'Add Fractal' and 'Exit'
You can also see that both are on the mainwindow.ui file:
But when I run the project, the window is not showing as I wish. Tabs are not showing.
I had build, rebuild and make, and still have this strange thing.
Can anyone give me a hand?
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
void createActions();
void createMenus();
// Widgets i layouts
QWidget *centralWidget;
// Accions associades als menus
QAction *exitAct;
// Menus principals
QMenu *fileMenu;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
centralWidget = new QWidget;
setCentralWidget(centralWidget); createActions();
createMenus();
setWindowTitle(tr("Practica 1: GiVD 2011-2012"));
resize(640, 480);
}
void MainWindow::createActions() {
exitAct = new QAction(tr("&Exit"), this);
exitAct->setShortcut(tr("Ctrl+Q"));
exitAct->setStatusTip(tr("Sortir del programa"));
connect(exitAct, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));
}
void MainWindow::createMenus()
{
fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addSeparator();
// Per a cada nou submenú has de fer un addAction
fileMenu->addAction(exitAct);
}
MainWindow::~MainWindow()
{
delete ui;
}
main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget"/>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>22</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionAdd_Fractal"/>
<addaction name="actionExit"/>
</widget>
<addaction name="menuFile"/>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
<action name="actionAdd_Fractal">
<property name="text">
<string>Add Fractal</string>
</property>
</action>
<action name="actionExit">
<property name="text">
<string>Exit</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
I got into the same issue until I realized that menu's on a mac OS appear at the top and not at the application window.
See if this is the case for you.
Thanks,

Resources