I'm developing a basic web browser in QT5 (IDE Qt Creator 2.6.2).
If I click on a link\anchor with target:
<a target="newWindow" href="http://stackoverflow.com">Test</a>
or execute an event that opens a pop-up (onclick, onmouseover, onkeydown, etc.):
<input type="button" value="Test" onclick="window.open('','newWindow');">
and close the newly opened window then I can not reopen that window. I click and nothing happens.
Following code to test:
test-qwebview.pro
QT += webkitwidgets network core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = browserqt
TEMPLATE = app
SOURCES += main.cpp\
mbrowserqt.cpp
HEADERS += mbrowserqt.h
FORMS += mbrowserqt.ui
# install
target.path = $$[QT_INSTALL_EXAMPLES]/webkitwidgets/previewer
INSTALLS += target
mbrowserqt.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>mBROWSERQT</class>
<widget class="QMainWindow" name="mBROWSERQT">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>640</width>
<height>320</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="windowTitle">
<string>Browser QT5</string>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="documentMode">
<bool>false</bool>
</property>
<property name="tabShape">
<enum>QTabWidget::Rounded</enum>
</property>
<widget class="QWidget" name="centralWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetMaximumSize</enum>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWebView" name="mybrowsertest">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>50</width>
<height>50</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="url">
<url>
<string>about:blank</string>
</url>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<layoutdefault spacing="0" margin="0"/>
<customwidgets>
<customwidget>
<class>QWebView</class>
<extends>QWidget</extends>
<header>QtWebKitWidgets/QWebView</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
mbrowserqt.h
#ifndef mBROWSERQT_H
#define mBROWSERQT_H
#include <QMainWindow>
namespace Ui {
class mBROWSERQT;
}
class mBROWSERQT : public QMainWindow
{
Q_OBJECT
public:
explicit mBROWSERQT(QWidget *parent = 0, bool q = false);
~mBROWSERQT();
private:
Ui::mBROWSERQT *ui;
//adicionado
public slots:
void closeMyWindow();
void resizeMyWindow(const QRect & geom);
};
#endif // mBROWSERQT_H
mbrowserqt.cpp
#include "mbrowserqt.h"
#include "ui_mbrowserqt.h"
#include <QtNetwork>
QWebSettings *settings;
class myWebPage : public QWebPage
{
bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type){
url = request.url();
return QWebPage::acceptNavigationRequest(frame,request,type);
}
virtual QWebPage * createWindow(QWebPage::WebWindowType type) {
Q_UNUSED(type);
QMainWindow *wx = new mBROWSERQT(NULL,true);
QWebView *wv = wx->findChild<QWebView*>("mybrowsertest");
//Test
connect(wv->page(), SIGNAL(windowCloseRequested()), wx, SLOT(deleteLater()));
wx->showNormal();
return wv->page();
}
private:
QUrl url;
};
mBROWSERQT::mBROWSERQT(QWidget *parent, bool q) :
QMainWindow(parent),
ui(new Ui::mBROWSERQT)
{
ui->setupUi(this);
ui->mybrowsertest->setPage(new myWebPage());
settings = QWebSettings::globalSettings();
settings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls,true);
settings->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled,true);
settings->setAttribute(QWebSettings::LocalContentCanAccessFileUrls,true);
settings->setAttribute(QWebSettings::JavascriptCanOpenWindows,true);
settings->setAttribute(QWebSettings::JavascriptCanCloseWindows,true);
settings->setAttribute(QWebSettings::JavascriptEnabled,true);
settings->setAttribute(QWebSettings::PluginsEnabled,true);
connect(ui->mybrowsertest->page(), SIGNAL(windowCloseRequested()), this, SLOT(closeMyWindow()));
connect(ui->mybrowsertest->page(), SIGNAL(geometryChangeRequested(const QRect)),
this, SLOT(resizeMyWindow(const QRect)));
qDebug() << "new Page (target or window.open): " << q;
if(q==false){
QString fPage = "<!DOCTYPE html>";
fPage.append("<html>\n");
fPage.append("<head>\n");
fPage.append("<script>\n");
fPage.append("function openWin(q){\n");
fPage.append("try{\n");
fPage.append("var myWindow=window.open('','test','width=200,height=100,top=50,left=50');\n");
fPage.append(" myWindow.document.write(\"<p>This is 'myWindow'</p>\");\n");
fPage.append("} catch (ee){ alert(ee); } }\n");
fPage.append("</script>\n");
fPage.append("</head>\n");
fPage.append("<body>\n");
fPage.append("<p><input type=\"button\" value=\"Test window.open\" onclick=\"openWin();\"></p>\n");
fPage.append("<p><a target=\"newWindow\" href=\"http://stackoverflow.com\">Test target</a></p>\n");
fPage.append("</body>\n");
fPage.append("</html>");
ui->mybrowsertest->setHtml(fPage);
}
}
void mBROWSERQT::resizeMyWindow(const QRect & geom){
qDebug() << "geometry: " << geom;
this->setGeometry(geom);
}
void mBROWSERQT::closeMyWindow(){
qDebug() << "closeMyWindow/webView::stop...";
ui->mybrowsertest->stop();
qDebug() << "closeMyWindow/webView::page::view::close()...";
ui->mybrowsertest->page()->view()->close();
qDebug() << "closeMyWindow/webView::page::view::deleteLater()...";
ui->mybrowsertest->page()->view()->deleteLater();
qDebug() << "closeMyWindow/webView::close()...";
ui->mybrowsertest->close();
qDebug() << "closeMyWindow/MainWindow::close()...";
close();//close widget
deleteLater();//close Object
}
mBROWSERQT::~mBROWSERQT()
{
delete ui;
}
main.cpp
#include "mbrowserqt.h"
#include <QApplication>
#include <QtWebKitWidgets/QWebView>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
mBROWSERQT w;
w.show();
return a.exec();
}
I removed: closeMyWindow
add virtual function: QMainWindow::closeEvent(QCloseEvent *event)
Using QWebFrame::evaluateJavaScript I run a javascript that sends the close command using javascript:
Add attribute QWEBVIEW->setAttribute(Qt::WA_DeleteOnClose, true);
Full fixed source:
mbrowserqt.h
#ifndef mBROWSERQT_H
#define mBROWSERQT_H
#include <QMainWindow>
namespace Ui {
class mBROWSERQT;
}
class mBROWSERQT : public QMainWindow
{
Q_OBJECT
public:
explicit mBROWSERQT(QWidget *parent = 0, bool q = false);
~mBROWSERQT();
private:
Ui::mBROWSERQT *ui;
//adicionado
public slots:
void closeEvent(QCloseEvent *event);
void resizeMyWindow(const QRect & geom);
};
#endif // mBROWSERQT_H
mbrowserqt.cpp
#include "mbrowserqt.h"
#include "ui_mbrowserqt.h"
#include <QtNetwork>
#include <QWebFrame>
QWebSettings *settings;
class myWebPage : public QWebPage
{
bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type){
url = request.url();
return QWebPage::acceptNavigationRequest(frame,request,type);
}
virtual QWebPage * createWindow(QWebPage::WebWindowType type) {
Q_UNUSED(type);
QMainWindow *wx = new mBROWSERQT(NULL,true);
QWebView *wv = wx->findChild<QWebView*>("mybrowsertest");
wv->setAttribute(Qt::WA_DeleteOnClose, true);
wx->showNormal();
return wv->page();
}
private:
QUrl url;
};
mBROWSERQT::mBROWSERQT(QWidget *parent, bool q) :
QMainWindow(parent),
ui(new Ui::mBROWSERQT)
{
ui->setupUi(this);
ui->mybrowsertest->setAttribute(Qt::WA_DeleteOnClose, true);
ui->mybrowsertest->setPage(new myWebPage());
settings = QWebSettings::globalSettings();
settings->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls,true);
settings->setAttribute(QWebSettings::OfflineStorageDatabaseEnabled,true);
settings->setAttribute(QWebSettings::LocalContentCanAccessFileUrls,true);
settings->setAttribute(QWebSettings::JavascriptCanOpenWindows,true);
settings->setAttribute(QWebSettings::JavascriptCanCloseWindows,true);
settings->setAttribute(QWebSettings::JavascriptEnabled,true);
settings->setAttribute(QWebSettings::PluginsEnabled,true);
connect(ui->mybrowsertest->page(), SIGNAL(windowCloseRequested()), this, SLOT(closeMyWindow()));
connect(ui->mybrowsertest->page(), SIGNAL(geometryChangeRequested(const QRect)),
this, SLOT(resizeMyWindow(const QRect)));
qDebug() << "new Page (target or window.open): " << q;
if(q==false){
QString fPage = "<!DOCTYPE html>";
fPage.append("<html>\n");
fPage.append("<head>\n");
fPage.append("<script>\n");
fPage.append("function openWin(q){\n");
fPage.append("try{\n");
fPage.append("var myWindow=window.open('','test','width=200,height=100,top=50,left=50');\n");
fPage.append(" myWindow.document.write(\"<p>This is 'myWindow'</p>\");\n");
fPage.append("} catch (ee){ alert(ee); } }\n");
fPage.append("</script>\n");
fPage.append("</head>\n");
fPage.append("<body>\n");
fPage.append("<p><input type=\"button\" value=\"Test window.open\" onclick=\"openWin();\"></p>\n");
fPage.append("<p><a target=\"newWindow\" href=\"http://stackoverflow.com\">Test target</a></p>\n");
fPage.append("</body>\n");
fPage.append("</html>");
ui->mybrowsertest->setHtml(fPage);
}
}
void mBROWSERQT::resizeMyWindow(const QRect & geom){
qDebug() << "geometry: " << geom;
this->setGeometry(geom);
}
void mBROWSERQT::closeEvent(QCloseEvent *event) {
Q_UNUSED(event);
ui->mybrowsertest->close();
}
mBROWSERQT::~mBROWSERQT()
{
delete ui;
}
Related
Problem
I am developing a program with QT. Recently I found that sometimes calling the repaint method of the QLabel control takes two or three seconds in a slot function when I emit a signal in a thread. While sometimes it takes only about one millisecond. There is a difference when I make it sleep for different seconds in the run function of the thread. Here is 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.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "testthread.h"
#include <QDateTime>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
TestThread *m_testThread; //thread
private slots:
void onTestSlot();
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_testThread = new TestThread();
connect(m_testThread, &TestThread::sigTest, this, &MainWindow::onTestSlot);
m_testThread->start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onTestSlot()
{
ui->label_resultSimilarity->setText("test");
qDebug() << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss:zzz") << ":【MainWindow::onTestSlot】start repaint";
ui->label_resultSimilarity->repaint();
qDebug() << QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss:zzz") << ":【MainWindow::onTestSlot】end repaint";
}
testthread.h
#ifndef FACERECOGNIZETHREAD_H
#define FACERECOGNIZETHREAD_H
#include <QThread>
#include <QImage>
#include <QDebug>
#include <QMainWindow>
class TestThread: public QThread
{
Q_OBJECT
public:
TestThread();
protected:
void run();
signals:
void sigTest();
};
#endif // FACERECOGNIZETHREAD_H
testthread.cpp
#include "testthread.h"
#include <QApplication>
TestThread::TestThread()
{
}
void TestThread::run()
{
//QThread::msleep(200);
QThread::msleep(500);
emit sigTest();
}
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>817</width>
<height>478</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QLabel" name="label_preview">
<property name="geometry">
<rect>
<x>93</x>
<y>9</y>
<width>571</width>
<height>401</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="text">
<string/>
</property>
<property name="scaledContents">
<bool>false</bool>
</property>
</widget>
<widget class="QWidget" name="widget" native="true">
<property name="geometry">
<rect>
<x>679</x>
<y>10</y>
<width>131</width>
<height>381</height>
</rect>
</property>
<widget class="QLabel" name="label_resultImage">
<property name="geometry">
<rect>
<x>10</x>
<y>20</y>
<width>111</width>
<height>151</height>
</rect>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="text">
<string/>
</property>
</widget>
<widget class="QLabel" name="label_resultSimilarity">
<property name="geometry">
<rect>
<x>20</x>
<y>210</y>
<width>91</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string/>
</property>
</widget>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>817</width>
<height>23</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>
Additional remarks
After I edit the run method in testthread.cpp and make it sleep for 500 miliseconds, I would get the following result after I exec the program:
"2021-05-26 00:15:31:641" :【MainWindow::onTestSlot】start repaint
"2021-05-26 00:15:34:605" :【MainWindow::onTestSlot】end repaint
However, after I edit the run method in testthread.cpp again and make it sleep for 200 miliseconds, I would get the following result after I exec the program:
"2021-05-26 00:14:55:954" :【MainWindow::onTestSlot】start repaint
"2021-05-26 00:14:55:970" :【MainWindow::onTestSlot】end repaint
I donot know why the gui thread respond to the repaint so slow. Is there any solutions to make it respond quickly? Thanks for any assistance.
If you want ui updated immediatly,could change connection mode to 'Qt::BlockingQueueConnection'.And does the 'repaint()' calling is necessary after 'setData' method ?
Good Luck~
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(¢ral);
QMediaPlayer player;
player.setMedia(QUrl::fromLocalFile("dolbycanyon.mov"));
player.setVideoOutput(¢ral);
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();
}
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
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QMouseEvent>
#include <QTimer>
#include <QWidget>
#include <windowsx.h>
#include <Windows.h>
#include <QtTest>
#include <QDesktopWidget>
#include <QApplication>
std::vector<QPoint> poz;
int i=0;
int a=0;
double timer_time=10;
bool certain=false;
bool mouse_clicked=true;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->centralWidget->setStyleSheet("background-color: #535353;" "color: white;");
ui->click_on->setStyleSheet("color: #ceb008;");
ui->speed_label->setText(QString::number(timer_time));
//this->setWindowFlags(Qt::WindowStaysOnTopHint);
this->setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint); //no_frames and always_on_top
Qt::X11BypassWindowManagerHint;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(clicked())); //set cursor position timer
timer_move = new QTimer(this);
connect(timer_move, SIGNAL(timeout()), this, SLOT(repeat())); //move cursor timer
timer_points = new QTimer(this);
connect(timer_points, SIGNAL(timeout()), this, SLOT(points())); //points timer
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_start_clicked()
{
if (!certain) timer->start(timer_time);
else timer_points->start(timer_time);
}
void MainWindow::on_stop_clicked()
{
timer->stop();
}
void MainWindow::clicked()
{
p = QCursor::pos();
poz.push_back(p);
ui->xy->setText("x: "+QString::number(p.rx())+" y: "+QString::number(p.ry()));
ui->list->appendPlainText("x: "+QString::number(poz[i].rx())+" y: "+QString::number(poz[i].ry()));
i++;
}
void MainWindow::on_hide_clicked()
{
this->setWindowFlags(Qt::WindowStaysOnBottomHint);
}
void MainWindow::on_off_clicked()
{
exit(0);
}
void MainWindow::on_repeat_clicked()
{
ui->repeat->setStyleSheet("color: #ceb008;");
repeat();
}
void MainWindow::repeat(){
//int x=1027;
//int y=322;
int x=rand()%1920;
int y=rand()%1080;
on_stop_clicked();
if(a==0) {timer_move->start(timer_time);}
if(a<i) {
this->cursor().setPos(poz[a].rx(), poz[a].ry());
// QPointF p(rand()%1920,rand()%1080);
// QMouseEvent(QEvent::MouseButtonPress, p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
// QMouseEvent(QEvent::MouseButtonRelease, p, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
//QTest::mousePress(this,);
// QTest::mouseRelease();
//QTest::mouseClick(this,Qt::LeftButton,Qt::NoModifier,poz[a]);
// QTest::mouseClick (this, Qt::LeftButton, Qt::NoModifier, QPoint(660, 1060), 100);
//QWidget *d = QApplication::desktop()->screen();
//QTest::mouseClick(d, Qt::LeftButton, Qt::NoModifier, QPoint(x,y));
HWND h = GetForegroundWindow();
WORD mouseX = 10;// x coord of mouse
WORD mouseY = 10;// y coord of mouse
PostMessage(h,WM_LBUTTONDOWN,0,MAKELPARAM(mouseX,mouseY));
//QMouseEvent e(QEvent::MouseButtonPress, poz[a], Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
//QApplication::sendEvent(ui->centralWidget, &e);
a++;}
else a=0;
}
void MainWindow::on_repeat_off_clicked()
{
timer_move->stop();
a=0;
ui->repeat->setStyleSheet("color: white;");
}
void MainWindow::on_points_clicked()
{
if (certain==false) {
certain=true;
ui->points->setStyleSheet("color: #ceb008;");
}
else {
certain=false;
ui->points->setStyleSheet("color: white;");
}
}
void MainWindow::keyReleaseEvent(QKeyEvent *e){
switch(e->key()){
case Qt::Key_Comma: clicked();
e->accept();
break;
}
}
void MainWindow::points(){
p = QCursor::pos();
ui->xy->setText("x: "+QString::number(p.rx())+" y: "+QString::number(p.ry()));
}
void MainWindow::on_clear_clicked()
{
timer->stop();
timer_move->stop();
poz.erase(poz.begin(),poz.end());
i=0;
a=0;
timer_time=10;
certain=false;
ui->xy->setText("");
ui->list->clear();
}
void MainWindow::on_speed_clicked()
{
ui->speed_label->setReadOnly(false);
ui->speed->setStyleSheet("color: #ceb008;");
}
void MainWindow::on_speed_label_textChanged()
{
ui->speed_label->setReadOnly(true);
timer_time=(ui->speed_label->toPlainText()).toDouble();
ui->speed->setStyleSheet("color: white;");
}
void MainWindow::on_click_on_clicked()
{
if (mouse_clicked) {
ui->click_on->setStyleSheet("color: white;");
mouse_clicked=false;
}
else {
ui->click_on->setStyleSheet("color: #ceb008;");
mouse_clicked=true;}
}
mainwidnow.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();
QTimer *timer; //timer for capture a cursor
QTimer *timer_move; //timer for set cursor position
QTimer *timer_points; //timer for certain points
QPoint p;
private slots:
void on_start_clicked();
void on_stop_clicked();
void clicked();
void on_hide_clicked();
void on_off_clicked();
void on_repeat_clicked();
void repeat();
void on_repeat_off_clicked();
void on_points_clicked(); //choose points with tab
void points();
void keyReleaseEvent(QKeyEvent *e);
void on_clear_clicked();
void on_speed_clicked();
void on_speed_label_textChanged();
void on_click_on_clicked();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
autoclicker.pro
#-------------------------------------------------
#
# Project created by QtCreator 2017-04-30T09:25:20
#
#-------------------------------------------------
QT += core gui testlib
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = autoclicker
TEMPLATE = app
# The following define makes your compiler emit warnings if you use
# any feature of Qt which as been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
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>419</width>
<height>431</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QStackedWidget" name="gridStackedWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>421</width>
<height>381</height>
</rect>
</property>
<widget class="QWidget" name="gridStackedWidgetPage1">
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<property name="verticalSpacing">
<number>25</number>
</property>
<item row="10" column="1">
<widget class="QTextEdit" name="speed_label">
<property name="layoutDirection">
<enum>Qt::LeftToRight</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QPushButton" name="repeat">
<property name="text">
<string>REPEAT (SHIFT + R)</string>
</property>
<property name="shortcut">
<string>Shift+R</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="points">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>CHOOSE POINTS (SHIFT + P) - PRESS COMMA ( , )</string>
</property>
<property name="shortcut">
<string>Shift+P</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="start">
<property name="text">
<string>START (SHIFT + S)</string>
</property>
<property name="shortcut">
<string>Shift+S</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="xy">
<property name="maximumSize">
<size>
<width>195</width>
<height>16777215</height>
</size>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="hide">
<property name="text">
<string>HIDE (SHIFT + H)</string>
</property>
<property name="shortcut">
<string>Shift+H</string>
</property>
</widget>
</item>
<item row="6" column="0" rowspan="3">
<widget class="QPlainTextEdit" name="list"/>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="stop">
<property name="text">
<string>STOP (SHIFT + SPACE)</string>
</property>
<property name="shortcut">
<string>Shift+Space</string>
</property>
<property name="autoRepeat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="7" column="1">
<widget class="QPushButton" name="repeat_off">
<property name="text">
<string>REPEAT OFF (SHIFT + F)</string>
</property>
<property name="shortcut">
<string>Shift+F</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QRadioButton" name="off">
<property name="text">
<string>OFF (SHIFT + O)</string>
</property>
<property name="shortcut">
<string>Shift+O</string>
</property>
</widget>
</item>
<item row="10" column="0">
<widget class="QPushButton" name="speed">
<property name="text">
<string>SET SPEED (SHIFT + A)</string>
</property>
<property name="shortcut">
<string>Shift+A</string>
</property>
</widget>
</item>
<item row="8" column="1">
<widget class="QPushButton" name="clear">
<property name="text">
<string>CLEAR (SHIFT + C)</string>
</property>
<property name="shortcut">
<string>Shift+C</string>
</property>
</widget>
</item>
<item row="11" column="0">
<widget class="QPushButton" name="click_on">
<property name="text">
<string>MOUSE CLICK ON/OFF (SHIFT + M)</string>
</property>
<property name="shortcut">
<string>Shift+M</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
Why there is an error?
mainwindow.obj:-1: błąd: LNK2019: unresolved external symbol __imp_GetForegroundWindow referenced in function "private: void __cdecl MainWindow::repeat(void)" (?repeat#MainWindow##AEAAXXZ)
AND
mainwindow.obj:-1: błąd: LNK2019: unresolved external symbol __imp_PostMessageW referenced in function "private: void __cdecl MainWindow::repeat(void)" (?repeat#MainWindow##AEAAXXZ)
How to do this right? I want in void repeat to mouse click over the screen (even outside app). How to do this?
(Posted solution on behalf of the OP).
It works now. Thanks. I used:
LIBS += -luser32
in my project file and:
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);
in my code.
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,