I create a simple web browser with Qt 5.7 and the webEngine.
I would like to create an search function to find word in webView but I don't really know how make interaction between web content and Qt ( I'm new on Qt, I do this for fun and to improve my level ).
this is the minimal code too display WebView :
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.showMaximized();
return a.exec();
}
mainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtWebEngineWidgets>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void setWebEngine();
private:
Ui::MainWindow *ui;
QWebEngineView *view;
};
#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);
setWebEngine();
setCentralWidget(view);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::setWebEngine()
{
view = new QWebEngineView();
view->load(QUrl("http://www.google.com"));
}
I would like to know something else, is it possible to list elements in the web content ( form, h1, h2, ... )
Have a nice day, and sorry for my English ;)
From the Qt5 documentation
void QWebEngineView::findText(const QString &subString, QWebEnginePage::FindFlags options = QWebEnginePage::FindFlags())
Finds the specified string, subString, in the page, using the given
options.
To clear the selection, just pass an empty string.
See also selectedText() and selectionChanged().
Should be quite simple.
Related
I am trying to make a window with a QWebEngineView, and delete the QWebEngineView after the window closes. However, the QWebEngineView never seems to get deleted, and keeps running any QUrl I have loaded (e.g. a YouTube video). In my program, I have a QMainWindow with a Line Edit and a Push Button, that creates a window that loads the URL entered by the user. Here is my code:
MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "subwindow.h"
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
void init();
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
SubWindow *sub;
};
#endif // MAINWINDOW_H
SubWindow.h
#ifndef SUBWINDOW_H
#define SUBWINDOW_H
#include <QMainWindow>
#include <QtWebEngineWidgets/qwebengineview.h>
#include <QTimer>
namespace Ui
{
class SubWindow;
}
class SubWindow : public QMainWindow
{
Q_OBJECT
public:
explicit SubWindow(QWidget *parent = 0);
void doWeb(QString link);
~SubWindow();
private:
Ui::SubWindow *ui;
QWebEngineView *web;
private slots:
void on_pushButton_clicked();
};
#endif // SUBWINDOW_H
MainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::init()
{
this->showMaximized();
sub = new SubWindow(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
sub->doWeb(ui->lineEdit->text());
}
SubWindow.cpp
#include "subwindow.h"
#include "ui_subwindow.h"
SubWindow::SubWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::SubWindow)
{
ui->setupUi(this);
}
void SubWindow::doWeb(QString link)
{
this->show();
web = new QWebEngineView(this);
ui->verticalLayout->addWidget(web);
web->load(QUrl(link, QUrl::TolerantMode));
web->show();
}
SubWindow::~SubWindow()
{
delete web; //Doesn't seem to work, since memory is still allocated in task manager
delete ui;
}
void SubWindow::on_pushButton_clicked()
{
this->close(); //Artifact for testing purposes.
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.init();
return a.exec();
}
I have also tried using "web->close();" (which I put on the line where I have the testing artifact) in conjunction with
"web->setAttribute(Qt::WA_DeleteOnClose);" (which I put after "web = new QWebEngineView(this);"), but that didn't solve my issue either. Anyone know what I am doing wrong?
You are creating QWebEngineView with parent "this" (owner) so you don't have to delete it yourself, it will be automatically deleted when it parent will. See Qt documentation about memory management :
http://doc.qt.io/qt-5/objecttrees.html
it is also dangerous doing that, because if you don't create the QWebEngineView object using doWeb(QString link), you will try to delete something that doesn't exist and therefore it can lead you to undefined behavior.
remove delete web from your destructor and see if you always have the problem.
Edit :
The reason why it is not destroyed : you aren't destroying SubWindow Object (the owner of QWebEngineView Object). You can Verify it yourself by printing something in the destructor.
If you were destroying SubWindow object, the second time you push the button in MainWindow, your application will crashes. Since you aren't creating the SubWindow object inside your function on_push_button, but inside MainWindow::init. Your SubWindow Object is only hidden and not destroyed. It is destroyed only when you close the MainWindow. You are also Creating an instance of QWebEngineview each time you show sub (SubWindow Object), so if you show sub 3 times you will have 3 QWebEngineView inside your Subwindow.
the changes i would do to the 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 "subwindow.h"
namespace Ui
{
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
SubWindow* sub;
};
#endif
mainWindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow), sub(new SubWindow(this))
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
sub->show();
sub->doWeb(ui->lineEdit->text());
}
subWindow.h
#ifndef SUBWINDOW_H
#define SUBWINDOW_H
#include <QMainWindow>
#include <QtWebEngineWidgets/qwebengineview.h>
#include <QTimer>
namespace Ui
{
class SubWindow;
}
class SubWindow : public QMainWindow
{
Q_OBJECT
public:
explicit SubWindow(QWidget *parent = 0);
void doWeb(QString link);
~SubWindow();
private:
Ui::SubWindow *ui;
QWebEngineView *web;
private slots:
void on_pushButton_clicked();
};
#endif // SUBWINDOW_H
subWindow.cpp
#include "subwindow.h"
#include "ui_subwindow.h"
SubWindow::SubWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::SubWindow),
web(new QWebEngineView(this))
{
ui->setupUi(this);
ui->verticalLayout->addWidget(web);
}
void SubWindow::doWeb(QString link)
{
web->load(QUrl(link, QUrl::TolerantMode));
}
SubWindow::~SubWindow()
{
delete ui;
}
void SubWindow::on_pushButton_clicked()
{
this->close(); //Artifact for testing purposes.
}
Note that i am also not destroying subWindow object, but i m not creating QWebView each time i call the method SubWindow::doWeb(String).
If it was up to me i would use a Subclassed Dialog that is not a member of MainWindow, the object would be created inside MainWindow::on_pushButton_clicked() and destroyed when i finish using it.
OK, apparently I needed to call "web->deleteLater();" before calling
"this->close();". The "delete web;" was uneeded. Still, I'd like to know why delete doesn't work in this case...
Looks like something was not closed correctly.
I was using Qt 5.15 using the kit MSVC2019 32bit compiler. But Visual Studio 2017 (and not 2019) was installed on my computer. Thus, the compiler detected in Qt creator -> project -> manage kit -> compiler was the one of MSVC2017 i.e : Microsoft visual C++ compiler 15.8 (x86).
The solution is to install visual Studio 2019 and then replace Qt creator by the correct compiler (2019) i.e: Microsoft visual c++ compiler 16.7 (X86).
Then I could compile without any leak of memory anymore.
I'm starting to learn Qt and coding. I have a basic project in mind, for practice purposes.
Here is a pic of my small UI:
Bear with me please because I am just starting in cpp.
I would like the QPushButton to append this string -> "text" inside the text box after I click it.
Clicking twice would result in having "texttext" and so on.
I have seen this question answered:
QT creating push buttons that add text to a text edit box
The solution mentioned there seems to be what I need, I just don't understand how to integrate it to my project.
Is there anyone that would be able to help out ?
I have these files so far:
test.pro:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = test
TEMPLATE = app
SOURCES += main.cpp\
mainwindow.cpp
HEADERS += mainwindow.h
FORMS += mainwindow.ui
mainwindow.h :
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void addTextTolable();
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();
}
and mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(this- >addTextToLabel()));
}
void MainWindow::addTextTolable()
{
ui->textEdit->appendPlainText("test");
}
MainWindow::~MainWindow()
{
delete ui;
}
This is the last error I have
mainwindow.cpp:-1: In member function 'void MainWindow::addTextTolable()':
mainwindow.cpp:14: error: 'class QTextEdit' has no member named 'appendPlainText'
ui->textEdit->appendPlainText("test");
^
Welcome to C++ and Qt coding! It's a lot of fun, but there are a lot of things going on. I'll try my best to modify your existing stuff to explain. Classes inherited from QObject send signals to each other through Qt's signal/slot architecture. So, this is what you'll do.
1.) Declare a slot function in the mainwindow header file. This is just a normal function declaration, except placed under a slots: tab.
2.) Connect the signal from the QPushButton's "clicked(bool)" to the mainwindow slot, usually in the MainWindow constructor
So here's the modified code.
mainwindow.h :
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
/*IMPORTANT NOTE: Q_OBJECT must appear in the beginning of the header of any object you want to use signals/slots for*/
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
/*Declare the function to be called when the QPushButton is clicked*/
private slots:
void addTextToLabel();
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();
}
and mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
/*It's very important to note that doing anything with the ui object must be done AFTER ui->setupUi(this) is called. The program will segfault otherwise*/
/*General connect syntax:
connect(object that will emit signal, SIGNAL(signal emitted), object that will receive the signal, SLOT(slot function));
/*the pushButton is owned by the ui object*/
connect(ui->pushButton, SIGNAL(clicked(bool)), this, SLOT(addTextToLabel());
}
/*Now define the slot function*/
void MainWindow::addTextToLabel()
{
/*I actually can't tell from the UI whether the text box is a plainTextEdit or textEdit, so substitute the name of the text box (found in the QDesigner window)*/
ui->textEdit->appendText("test");
}
MainWindow::~MainWindow()
{
delete ui;
}
Give that a shot and let me know if anything goes awry or you have any more questions.
I was trying to build a GUI for a project with an Arduino. The project itself is about a car-robot for harbor's containers management, and during the time it's on the development stage (and also on final release) would be cool to have a way to monitor and send commands to it. Seems a good idea to initially implement a communication via serial port and then rewrite/reuse the code for a radio communicator or something like that. The code was going well until some bugs come up.
First were used QSerialPort and QSerialPortInfo, following the example of several programs available at Qt's website. The compiler showed up with some errors about a missing "QT+=serialport" and about wrong forward declarations but after a while I could fix them. Then when the code to open a serial port was written, the program started to crash...
After some hours, this GUI Qt code (and a respective console version) works and exemplifies the problem:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/qserialport.h>
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow {
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
#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);
QSerialPort *connected_port;
connected_port = new QSerialPort;
}
MainWindow::~MainWindow() {
delete ui;
}
main.cpp
#include <QApplication>
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow {
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
};
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
However just after changing mainwindow.h and inserting QSerialPort *connected_port; in MainWindows's private section and removing it from mainwindow.cpp, this simple program starts to crash.
mainwindow.h
(...)
class MainWindow : public QMainWindow {
(...)
private:
QSerialPort *connected_port;
Ui::MainWindow *ui;
};
(...)
mainwindow.cpp
(...)
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
connected_port = new QSerialPort;
}
(...)
Will crash. In qt's terminal example is a similar approach, but I did not get the why it works and this code don't. How make it work?
Solved. For some reason, adding a "QT+=widgets" on the .pro file produced a functional program, aside the already added "QT+=serialport".
Ok I think is time to get some help, I have been practicing with signals and slots in Qt and I got stocked. What I want is to be able to change a label in mainwindow when a button in a QDialog is clicked. I have been searching and apparently the only way to do this is basically using signals and slots, here is what I have...
I have a mainwindow.ui with a button called "pushButton_OpenWindow" and a QLabel label_ShowText", I also have a externaldialog.ui that contains a QLineEdit called lineEdit_ExternalInput" and a QPushButton called "pushButton_SendText", and what I want is to change "label_ShowText" to whatever value "lineEdit_ExternalInput" is when pushButton_SendText" is clicked but it doesn't work, when I click the button nothing happens no errors, no warnings nothing.
Here is the code that doesn't work...
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 slots:
void on_pushButton_OpenWindow_clicked();
void textValue(const QString &newText);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "externaldialog.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ExternalDialog *externalDialog = new ExternalDialog;
// connecting signals and slots
QObject::connect(externalDialog, SIGNAL(textChanged(QString)), this, SLOT(textValue(QString)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_OpenWindow_clicked()
{
ExternalDialog mDialog;
mDialog.setModal(true);
mDialog.exec();
}
void MainWindow::textValue(const QString &newText)
{
ui->label_ShowText->setText(newText);
qDebug()<<"Message from textValue Function \n";
}
externaldialog.h
#ifndef EXTERNALDIALOG_H
#define EXTERNALDIALOG_H
#include <QDialog>
namespace Ui {
class ExternalDialog;
}
class ExternalDialog : public QDialog
{
Q_OBJECT
public:
explicit ExternalDialog(QWidget *parent = 0);
~ExternalDialog();
private:
Ui::ExternalDialog *ui;
signals:
void textChanged(const QString&);
public slots:
void on_pushButton_SendText_clicked();
};
#endif // EXTERNALDIALOG_H
externaldialog.cpp
#include "externaldialog.h"
#include "ui_externaldialog.h"
#include <QDebug>
ExternalDialog::ExternalDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::ExternalDialog)
{
ui->setupUi(this);
}
ExternalDialog::~ExternalDialog()
{
delete ui;
}
void ExternalDialog::on_pushButton_SendText_clicked()
{
emit textChanged(ui->lineEdit_ExternalInput->text());
qDebug()<<"Sent Message";
}
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Any idea what I'm I doing wrong? Any suggestion will be appreciated. Sorry I posted the whole code but sometimes is better to see the whole picture.
Thanks a lot
change function MainWindow::on_pushButton_OpenWindow_clicked() into this
void MainWindow::on_pushButton_OpenWindow_clicked()
{
externalDialog->setModal(true);
externalDialog->exec();
}
You have just create a new unconnected dialog in the original function.
I am writing a simple editor i Qt and C++. I want to have tabs, so after creating a new document, I want to open this in a new tab. My code:
// mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle("emacs");
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionExit_triggered()
{
qApp->exit(0);
}
void MainWindow::on_actionNew_triggered()
{
// what to write here?
}
// 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.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 slots:
void on_actionExit_triggered();
void on_actionNew_triggered();
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
I have successfully managed to create an action to exit the program. But when I try something like this: tabWidget->addTab(new QWidget(),"new tab"); is complaints that tabWidget was not declared in the scope. Anybody? Thanks!
tabWidget is not a member of your MainWindow class, I'm guessing its an object you defined in your ui file, so try:
ui->tabWidget->addTab(...);