nearly searching for hours I became more confused about the Multithreading concept and I need help understanding and implementing it. After searching I have come to the following implementation
main.cpp
#include <QtGui/QApplication>
#include "mainwindow.h"
#include <mythread1.h>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
mythread abc;
abc.start();
abc.wait();
return a.exec();
}
In above code mythread.h is my header file which I created for multithreading and below is my code of mythread1.h
mythread1.h
#ifndef MYTHREAD1_H
#define MYTHREAD1_H
#include <QtGui>
#include <windows.h>
class mythread : public QThread
{
public:
void run();
};
void mythread::run()
{
}
#endif // MYTHREAD_H
Now my questions are
I have defined only one function run() and when the thread is initialized how compiler determines it has to execute run() function and what it does when it has multiple functions, I got this question because in main.cpp I just typed abc.start(); and didn't specify what to execute?
Inside mythread1.h and in run function I made a infinite loop using while(0<1) and ran the program and to my surprise I was just presented with white screen with 100% CPU usage(not a surprise), but it should run concurrently without interfering with main thread right? then why this is happening?
I then used QFile::copy("pathtomytargetfile","targetpath"); inside the run function inside in mythread1.cpp but that didn't work :O and it didn't copy that file but when i connected it with Push button in main thread then it got successfully copied, why this happened?
Does anyone know a simpler way to implement multithreading?
Thank you
First of all: run method should be protected!
Secondly, what do you mean by "I have defined only one function run()". You defined method, not function. abc.start() means that abc instance of mythread will start and use it's entry point method void run(). You can't declare more than one method with same signature. And if you wonder how it calls your run() instead of QThread::run() then you need to read something about virtual methods in C++
Ad. 3: How can we tell why your file didn't copy? Check what errors QFile provides you. Change your code something like that:
QFile f("pathtomytargetfile");
if( ! f.copy("targetpath") )
{
qDebug() << f.errorString();
}
It will provide you some usefull info
My answer might confuse you even more, but the following links are worth reading in my opinion:
This is an article by the engineer who introduced the QThread class. He apologizes for suggesting that inheriting from QThread is the way to go.
This article shows you, how you should do it (strictly speaking -- inheriting from QThread will work as well, it just is not as nice design-wise).
On this page you can find an overview of multithreading techniques that Qt offers and some help deciding which one you should use for your specific problem.
HTH
Related
My task is to create a QSettings wrapper class (wrapping is mostly needed by QML) which I can reach everywhere from the model, too.
The obvious choice is a static global instance of this class. However the problem is with this approach is that it's destroyed after main, after QApplication is destroyed, thus giving me the following warning:
QApplication::qAppName: Please instantiate the QApplication object first
Here is a simplified, sample code showing a really simple wrapper, and the destruction phases:
#include <QCoreApplication>
#include <QDebug>
#include <QGlobalStatic>
#include <QSettings>
#include <QTimer>
class Settings: public QObject
{
public:
~Settings() { qDebug() << "~Settings"; }
QSettings settings;
};
Q_GLOBAL_STATIC(Settings, globalSettings)
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
QObject::connect(&app, &QCoreApplication::aboutToQuit, [](){qDebug() << "~QCoreApplication aboutToQuit";});
QObject::connect(&app, &QCoreApplication::aboutToQuit, [](){globalSettings->settings.setValue("Hi", 2);});
QObject::connect(&app, &QCoreApplication::destroyed, [](){qDebug() << "~QCoreApplication destroyed";});
QTimer::singleShot(0, &app, SLOT(quit()));
return app.exec();
}
It prints out the following:
~QCoreApplication aboutToQuit
~QCoreApplication destroyed
~Settings
QApplication::qAppName: Please instantiate the QApplication object first
My question is: providing, in my program QSettings is used after QCoreApplication::aboutToQuit is emitted but before QCoreApplication::destroyed, how can I avoid this warning?
Using QSettings
I've used QSettings in pretty much every project I've ever made. Here is the pattern that I tend to use it:
in main.cpp
#include <QSettings>
//...
// Then in main(), after QApplication is instantiated, but before any settings are accessed
QSettings::setDefaultFormat(QSettings::IniFormat);
QApplication::setOrganizationName("MyOrg");
QApplication::setApplicationName("MyApp"):
Then anytime you are about to access QSettings, you just do this:
QSettings s;
s.value(// reading a value
s.setValue(// writing a value
Everything gets saved in the User Scope in an INI text file. It will be located in Windows under C:/Users/<username>/AppData/Roaming/MyOrg/MyApp.ini.
This usage of QSettings (IMHO) is very clean, doesn't require global variables or static references and is very fast and efficient. And it is very readable.
Now to be able to have things load settings at the right times, and not get the errors you mentioned in your question, see the initial example in the links below:
http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application
http://doc.qt.io/qt-5/qtwidgets-mainwindows-application-example.html
It works much better in the timeline of a Qt application and works great. I tend to make a readSettings and writeSettings for most of my GUI classes and for a number of my backend classes. readSettings happens when the widget has its showEvent or constructor happen and the writeSettings happens in the closeEvent. Also if I have a dedicated settings dialog, I emit a signal to have any affected classes to readSettings, right after the settings dialog writes those specific settings.
If you use the QML port of QSettings, it also uses the Organization name and Application name and the default format of QSettings to pick its filename and location.
http://doc.qt.io/qt-5/qml-qt-labs-settings-settings.html
I believe the default functionality of that QML component is just to read the setting when the component is created, and to write the setting whenever QML changes it. So to change it from C++ and have it recognized by QML, you should probably use the standard QML/C++ methods out there such as:
http://doc.qt.io/qt-5/qtqml-cppintegration-topic.html
And lastly if I am planning on installing defaults for a program that are decided for a build and I don't want to hardcode them, I hand write an INI file and have the installer place it in the system scope location: C:/ProgramData/MyOrg/MyApp.ini
And in the case that the settings of your program are more complex than what you want to store in an INI file, I would look into using QJson, and the SaveGame example.
Hope that helps.
I have a C++/Qt application which should have its GUI extensible with modules. Extending should be simple and versatile. I am just checking a concept - is it possible to have this main C++/Qt application that would execute a Python/PySide/PyQt script which would create a QWidget (or derived class) instance and embed this widget into the main C++/Qt application?
Is there any working snippet to demonstrate the feasibility of this task? I.e. how to create and embed the widget? How to pass signals between the application and the widget?
This question is a bit old, but in case someone else is face the same issue, I will try to give a useful answer.
I think it's possible. In the following example, I create a QApplication and QMainWindow in c++, embed a python interpreter, and then, on the python side, I create a QPushButton which I add to the main window.
Try this out:
#include <QApplication>
#include <QMainWindow>
#include <iostream>
#include "Python.h"
class PythonQt
{
public:
PythonQt()
{
char name[] = "test";
Py_SetProgramName(name);
Py_Initialize();
std::string code =
"from PySide import QtGui\n"
""
"all_widgets = QtGui.QApplication.instance().allWidgets()\n"
"window = None\n"
"for widget in all_widgets:\n"
" if str(widget.objectName()) == \"main_window\":\n"
" window = widget\n"
" break\n"
""
"def message_box():\n"
" QtGui.QMessageBox.information(None, 'Test', 'Hello!', \
QtGui.QMessageBox.Ok)\n"
" QtGui.QApplication.instance().quit()\n"
""
"button = QtGui.QPushButton('Press Me')\n"
"button.clicked.connect(message_box)\n"
"window.setCentralWidget(button)\n"
"window.move(600, 300)\n"
"window.show()";
PyRun_SimpleString(code.c_str());
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QMainWindow win;
win.setObjectName("main_window");
PythonQt python_code;
a.exec();
}
The python script is written here in a string to have everything in a single file, but you could of course read it in from a .py file.
Object ownership could be an issue though, as shown in the link given by Trilarion.
I don't think this is possible. PySide/PyQt are wrappers around C++/Qt. That means you create C++ objects and Python wrapper objects and somehow the wrapper objects kind of refer to the C++ objects. This works one way as far as I know.
But you want the other way. Basically a wrapper around Python objects (which themselves are wrappers around C++ objects) to use in C++. I don't think PySide/PyQt are ready for thise. However it is possible to embed Python in other languages.
Also see How to shoot yourself in the foot. about the pitfalls of communication between C++/Qt and Python.
The following works fine for localizing the QPrintDialog:
#include <QtGui/QApplication>
#include <QTranslator>
#include <QPrintDialog>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator translator;
if (translator.load("./translations/qt_de.qm")) {
a.installTranslator(&translator);
}
QPrintDialog printdialog;
printdialog.exec();
}
But when I click on the "Choose file"-Button (with the three dots) in the QPrintDialog, the english version of the file dialog comes up instead of the german one I'd like to have.
Also, there is a warning at the console:
KGlobal::locale::Warning your global KLocale is being recreated with a valid main component instead of a fake component, this usually means you tried to call i18n related functions before your main component was created. You should not do that since it most likely will not work
Where should I look?
As for the workaround mentioned here: Some QDialogs support a ::DontUseNativeDialog flag, but the QPrintDialog doesn't.
(tested on linux, don't know how the outcome is on other platforms)
try to add after translator.load this line:
a::installTranslator(&translator);//or something like that(*)
and read docs about QApplication::installTranslator methods...
(*) sorry I checked and it's a QCoreApplication's method. I used it into a QMainWindow subclass by qApp macro, i don't know how to call that from main.cpp. Please do some test.
I found myself having the same problem and I worked around it by adding to my main window:
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs);
You can find the enum with the attributes here.
I am just getting started in Qt, and trying to get a simplified, working example of the model-view-controller design pattern.
So far, I have been able to use signals and slots to connect basic widgets like push buttons to a QLabel, and have the view be modified as the push button is clicked/released. See code below for a working example of that (implemented in the MainWindow class).
I am trying to define a class, in this case, Game, which is going to be my model. I want Game to have all of the data and business rules of my entire application. I do not require that Game be anything Qt specific--it very well could be generic C++. However, in the code below, it does have some Qt-specific code to implement a QTimer which is useful for the purposes of this example.
I am trying to achieve two things in this example:
I want to have a model which is able to generate some sort of event within itself, like incrementing a variable value over the passage of time, and then ultimately see that change somehow reflected in the view. Or better yet, the timeout() of the QTimer could simply be the signal that is connected to some slot, that slot being some event that takes place within the model. Using the code shown below, the reflection in the view would be the setting of label_1 (part of the MainWindow class) to display one of the images already stored in imageOn or imageOff (also part of the MainWindow class).
I want to have the push button associated with the on_pushButton_clicked() and on_pushButton_pressed() slots be able to modify some value stored within the model. Then, coming full circle with item 1, have that update of the model be reflected in the view.
If my terminology thus far is incorrect or inconsistent with Qt terminology of MVC design pattern, forgive me. I would welcome any clarification on that. Also, if the example code I have provided is too convoluted for exemplifying the MVC design pattern in Qt, I am more than willing to wipe the slate clean and start with a more appropriate example. All I am trying to do is get started with Qt and MVC, but in a way that deals with more complex data types.
I am trying to develop an example in which I can handle a model and class such as Game which is potentially complex--not a simple list of QStrings or something guaranteed to be more straight-forward. When I browsed through the Qt documentation related to MVC, I came across a lot of examples that used the setModel() function to try and make the connections I am essentially outlining in list items 1 and 2. The problem was that I could not see a way of using that exact approach with a more complex data-type like Game which might be the entire data model for a complete application (I know Game is not complex in this example, but it could be eventually). I need something that is scalable and extensible, something that would work for an entire application. If those setModel()-type functions are suitable for this--which they very likely could be, I just could not figure it out on my own--I would like to know how to implement those in this example dealing with QLabel and images.
Code:
game.h
#ifndef GAME_H
#define GAME_H
#include <QtCore>
class Game : public QObject {
Q_OBJECT
public:
Game();
void timed_job();
private:
QTimer *timer;
};
#endif // GAME_H
game.cpp
#include "game.h"
#include <QtCore>
Game::Game() {
}
void Game::timed_job() {
timer = new QTimer(this);
timer->start(1000);
//connect(timer, SIGNAL(timeout()), this, SLOT(flip()));
}
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_clicked();
void on_pushButton_pressed();
private:
Ui::MainWindow *ui;
QImage imageOn, imageOff;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include <QImage>
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow) {
imageOn.load(":/Files/On.jpg");
imageOff.load(":/Files/Off.jpg");
ui->setupUi(this);
}
MainWindow::~MainWindow() {
delete ui;
}
void MainWindow::on_pushButton_clicked() {
ui->label_1->setPixmap(QPixmap::fromImage(imageOff));
}
void MainWindow::on_pushButton_pressed() {
ui->label_1->setPixmap(QPixmap::fromImage(imageOn));
}
main.cpp
#include <QtGui/QApplication>
#include <QLabel>
#include "mainwindow.h"
#include "game.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
A "controller" in Qt could technically be represented by a separate QObject subclass, containing just slots. And you would wire this between your model and view.
But normally what I do (and see) is to just make your model contain business logic, and your view subclass contain methods for handling it's user interactions. The closest I get to the controller concept is when I have my QMainWindow (or dialog) class that represents the application, and has a bunch of SLOTS on it. These slots get wired in to the private UI members signals to connect them together.
Example: Your main window has a model, a view, and a push button. In the init for the main window, I would set the model in the view, and connect the push button "clicked" to a slot on my window refreshData(). This slot would then call the "update" method on the model, which will automatically propagate to the view. The main window thus acts like a controller.
What you would want to do is to make some type of QAbstractItemModel or QStandardItemModel that represents your data and does what you want to update that data (a timer like you suggested). Any view connected to the model will be able to see it because of the standard interface. You can also just make a separate timer that places data into an existing QStandardItemModel
A note about custom QAbstractItemModel classes
As pointed out by #hyde, jumping into a custom model can be a challenge if you try and do it first, before getting a good understanding of the existing concrete model classes. Here is what I recommend doing:
Get familiar with the convenience widgets (QListWidget, QTableWidget, QTreeWidget)
Then try using a QStandardItemModel with a QListView/QTableView
Then work with QTreeView
Finally, when you really need very custom modeling for your existing data structures, you can work on subclassing QAbstractItemModel to make it use your own internal structure.
I'm guessing the answers to these questions will be very simple to anyone familiar with Qt. I'm trying to follow this intro tutorial for Qt: http://doc.qt.nokia.com/4.7-snapshot/gettingstartedqt.html. I get it up until the part that I've taken this screenshot for:
http://i160.photobucket.com/albums/t182/thinkpad20/qtintro.jpg
I understand these two code blocks well enough, but if I implement the widget as a class like they show here, what should I be putting in the main function of my code? It doesn't say anywhere. Also, when I try to compile this code, I get a "undefined reference to 'vtable for Notepad'" error. Can anyone help me out?
undefined reference to 'vtable for Notepad' almost certainly means you're not linking in the moc-generated files. The Qt docs mention it as a common mistake.
As for what to include in main, it normally involves the creation of an Application and a GUI element, then calling exec on the application. At its most basic, it might look like this:
#include <QApplication>
#include "notepad.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
Notepad mainWindow;
mainWindow.show();
return app.exec();
}