How to install QChartView in Qt Designer? - qt

My problem is identical with that from this topic: How to insert QChartView in form with Qt Designer? however I still cannot solve it.
I tried to download the plugin, but after typing qmake in the terminal, I get the following error:
Unknown test function: qtHaveModule
On the other hand, I can't use the first solution either. Where can I find the .pro file in Qt Designer (not qt creator) ?
Thank you in advance.

That problems usually comes because you are configuring your project with a older version of qmake, frequenctly for Qt4.
QtChart is available only in modern versions of Qt. If you are using QtCreator those are the steps to update your build system:
Go to:
Tools -> Options...
After that, go to:
Kits -> Qt Versions
Normally you should see the different versions of Qt that are installed. Check that you can see a modern version of Qt, QtCharts 2.0 was released with Qt 5.6.0, so that's your minimum version.
Now, updates your kits. If you are compiling a desktop app, check that your default Kit or the one you are using is using the proper Qt Version. You will find a combo-box where you can select the proper one.
After that, update and run again qmake.
Regarding your second problem, you don't edit your pro file in QtDesigner, you do it in QtCreator. Basically, open your project and add the Qt dependency:
QT += charts
Now, open your mainwindow.ui file or the file in which you want to insert the chart-view and follow the steps of the post you linked.
Example:
This is a classic .pro configuration:
QT += charts
SOURCES += \ main.cpp
In your main file, you should always add QT_CHARTS_USE_NAMESPACE on top. For instance, to display a line chart, you can do something like this:
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtCharts/QChartView>
#include <QtCharts/QLineSeries>
QT_CHARTS_USE_NAMESPACE
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
// Create your time series
QLineSeries *series = new QLineSeries();
series->append(0, 6);
series->append(2, 4);
series->append(3, 8);
series->append(7, 4);
series->append(10, 5);
*series << QPointF(11, 1) << QPointF(13, 3) << QPointF(17, 6) << QPointF(18, 3) << QPointF(20, 2);
// Configure your chart
QChart *chart = new QChart();
chart->legend()->hide();
chart->addSeries(series);
chart->createDefaultAxes();
chart->setTitle("Simple line chart example");
// Create your chart view
QChartView *chartView = new QChartView(chart);
chartView->setRenderHint(QPainter::Antialiasing);
// Display into a main window
QMainWindow window;
window.setCentralWidget(chartView);
window.resize(400, 300);
window.show();
return a.exec();
}
Source: Qt Example.
You just need to replace the final part for your special case:
...
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
...
// chartView is the name of the widget your promoted
...
// Create your chart view
ui->chartView->setRenderHint(QPainter::Antialiasing);
ui->chartView->setChart(chart);
}

Related

Replace QCameraViewfinder with QVideoWidget in Qt 6

I am trying to port some code to Qt 6's reworked QtMultimedia framework and running into a lot of issues of disappearing APIs.
One of these is QCameraViewfinder, which as I understand it, is a simple viewer of the current QCamera image feed.
It used to be a subclass of QVideoWidget, which still exists, and its documentation helpfully states the following:
Attaching a QVideoWidget to a QMediaPlayer or QCamera allows it to display the video or image output of that object.
player = new QMediaPlayer;
player->setSource(QUrl("http://example.com/myclip1.mp4"));
videoWidget = new QVideoWidget;
player->setVideoOutput(videoWidget);
videoWidget->show();
player->play();
Note: Only a single display output can be attached to a media object at one time.
Problem is, there is no way to do QCamera::setVideoOutput(QVideoWidget*) as that function does not exist.
Neither can I find an alternative API that connects the two.
Is this something that they forgot to provide or am I missing something?
I looked through the relevant classes' source code and documentation, but can't for the life of me find the magic incantation that's supposed to give me a simple view into a QCamera's current video feed.
You have to use QMediaCaptureSession:
#include <QApplication>
#include <QCamera>
#include <QMediaDevices>
#include <QMediaCaptureSession>
#include <QVideoWidget>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QVideoWidget videoWidget;
videoWidget.resize(640, 480);
videoWidget.show();
QCamera camera(QMediaDevices::defaultVideoInput());
camera.start();
QMediaCaptureSession mediaCaptureSession;
mediaCaptureSession.setCamera(&camera);
mediaCaptureSession.setVideoOutput(&videoWidget);
return a.exec();
}

qml systemtrayicon without qwidget/qapplication?

The last post here seems to imply that systemtrayicon no longer requires qwidget or qapplication... System tray icon without widgets
Ive given this a try and its not working for me. Am I correct in guessing this is an incorrect statement?
Put the sample code bellow and import.
in main.qml:
SystemTrayIcon {
visible: true
//icon.source: "qrc:/images/tray-icon.png"
onActivated: {
window.show()
window.raise()
window.requestActivate()
}
}
Error: QWidget: Cannot create a QWidget without QApplication
TL; DR; No, you have misunderstood. SystemTrayIcon needs you to use QApplication.
Explanation:
SystemTrayIcon is a QSystemTrayIcon wrapper that can be used in QML and therefore it is necessary to use QApplication, and that is indicated in the docs:
Availability
A native system tray icon is currently available on the following
platforms:
All window managers and independent tray implementations for X11 that implement the freedesktop.org XEmbed system tray specification.
All desktop environments that implement the freedesktop.org D-Bus StatusNotifierItem specification, including recent versions of KDE and
Unity.
All supported versions of macOS. Note that the Growl notification system must be installed for showMessage() to display messages on OS X
prior to 10.8 (Mountain Lion).
The Qt Labs Platform module uses Qt
Widgets as a fallback on platforms that do not have a native
implementation available. Therefore, applications that use types from
the Qt Labs Platform module should link to QtWidgets and use
QApplication instead of QGuiApplication.
To link against the QtWidgets library, add the following to your qmake
project file:
QT += widgets
Create an instance of QApplication in main():
#include <QApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
Note: Types in Qt.labs modules are not guaranteed to remain compatible
in future versions.
(emphasis mine)

How to use QGraphicsScene with QtGui/QGuiApplication?

I created a new Qt 5 project with QtCreator, and added the following lines to it.
#include <QGraphicsScene>
// in main():
QGraphicsScene scene;
In the .pro file I added:
Qt += gui
The object creation of QGraphicsScene is resulting in the segmentation fault.
What point am I missing?
EDIT:
I realized now that instead of QApplication my rest of the program is using QtGui/QGuiApplication.
How to use QGraphicsScene with QtGui/QGuiApplication?
You're correct: with QApplication it works for me in both Qt 4.8 and 5.2, but not with QGuiApplication:
#include <QApplication>
#include <QGraphicsScene>
#include <QTimer>
int main(int argc, char ** argv) {
QApplication app(argc, argv);
// With QGuiApplication, QGraphicsScene constructor crashes.
QGraphicsScene scene;
QTimer::singleShot(1000, &app, SLOT(quit()));
return app.exec();
}
You're incorrect in stating that the code will compile with just the gui module added to the project. Without the widgets module, your code won't compile, and this should have been the first hint that you're trying to do something that's not supported.
QGraphicsScene is not part of the gui module, but of the widgets module! All classes in the widgets module are free to assume (and they do!) that you've instantiated QApplication, not QGuiApplication! I've submitted it as QTBUG-36413, but - unsurprisingly - it got closed as invalid. It simply is not supposed to work.
If you want to use the QGuiApplication, there's a workaround:
The QApplication (but not QGuiApplication) is keeping a list of all graphics scenes. QGraphicsScene assumes that the type of qApp is QApplication. The list is accessed in QGraphicsScenePrivate::init(). The fix is to guard the reference to scene_list with a type check on qApp:
if (qobject_cast<QApplication*>(qApp))
You need this in both QGraphicsScenePrivate::init() and QGraphicsScene::~QGraphicsScene(). I've confirmed that after you recompile Qt, it doesn't crash anymore.
If you're serious about it, you'd have to copy relevant files from Qt's sources to your project, remove the widgets module from the project file, and patch things up until they work. Personally I think it's a waste of effort. It's trivial to render a QGraphicsView into an arbitrary paint device, without having to actually display it on the screen.

Qt Determine if application is launched from Qt Creator?

How can I from within my code determine if my application is started from Qt Creator (either by "F5" or "Ctrl + R")?
The reason why I want to know this is because I want to create my own debug message handler ( using qInstallMessageHandler()) only when the application is launched from the executable directly. Since Qt allows only one message handler, I don't want to create my own when launching from Qt Creator, or else I can't see the debug messages in Qt Creators own debug console.
I don't think there is an easy way to detect that.
You could add a command line argument to the run settings in QtCreator though, and check for that at runtime.
I have two possible solutions:
check the names of parent process (or parent of parent)
there are multiple ways to do this: under Posix (mingw, linux etc..) you have getppid(). Under Windows you can check the namehave the Psapi or other process handling functions. I have done this for other purposes in the past and it works reliably as long as the process names do not change. Alternatively you could check for the window names. Unfortunately none of these solutions are "Qt-Native".
supply a commandline argument only when started from Qt creator
If you use a library to scan commanline arguments this is probably the simplest solution. I usually use Boost Program Options (Google there). You could create a commandline argument like "--console-log" which specifies to put the logging output to the console. To set that option from within Qt Creator is documented here. This is probably the most "Qt-Native" solution. If you use Qt functions to parse the commandline, it is 100% Qt.
You can try IsDebuggerPresent or use only QDebug and check debug messages with debugview outside QT Creator.
You should google qInstallMessageHandler for more information.
But here goes the definitions:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtGui>
#include <QtWidgets>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
static void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
// If you're running lots of threads you'll need to do some research to
// determine if you need to make this synchronized (i.e. locked)
if(staticTextEdit) {
staticTextEdit->appendPlainText(msg + "\n");
}
}
private slots:
void on_pushButton_clicked();
private:
// There's lots of different ways to do this ... this was the quickest way for me.
static QPlainTextEdit* staticTextEdit;
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
Here are the declarations:
#include "mainwindow.h"
#include "ui_mainwindow.h"
QPlainTextEdit* MainWindow::staticTextEdit = NULL;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
staticTextEdit = ui->plainTextEdit;
qInstallMessageHandler(MainWindow::myMessageHandler);
}
MainWindow::~MainWindow()
{
delete ui;
}
// I'm using QtCreator to help create my slots. =).
void MainWindow::on_pushButton_clicked()
{
qDebug() << "CLICKED";
}
Here is a manual solution.
Define a macro in your .pro file....
# To turn on remove the comment marker '#'
# isEmpty(LAUNCH_FROM_IDE):LAUNCH_FROM_IDE = 1
!isEmpty(LAUNCH_FROM_IDE) {
DEFINES += APP_LAUNCH_FROM_IDE
}
And use in your header/source as needed...
#ifdef APP_LAUNCH_FROM_IDE
...
#endif
That's all
Not sure if this applies to the PC, but under OSX, when Qt Creator launches the application, it does it from the development build path; you can get the current launch path with:
QString expath = QCoreApplication::applicationDirPath();
Get that, dump it via qDebug(), and see where you're running from when launched from Qt. As long as that's not the location you run the application from when you're not launching it from within Qt, this should work.
I get this from the qDebug() when building and running in release mode from within Qt Creator:
"/Users/fyngyrz/build-iToolBox-Desktop_Qt_5_8_0_clang_64bit-Release/iToolBox.app/Contents/MacOS/iToolBox"
So for me, when building my app iToolBox I do the detection like this:
if (expath.indexOf("build-iToolBox-Desktop") != -1) // if we're running from inside Qt
{
}
else // we're not running from inside qt
{
}
Note1:
The release and build paths for Qt builds are different by default; so if you need this to work in both release and debug circumstances, you might have to do two checks of the path instead of one, depending on just what you're searching for.
Note 2:
If you incorporate this approach into your application, and the code will remain intact in the release build, be sure not to including anything in your search string that would incorporate any information you don't want to share, such as your real name which could be part of the path under some operating systems, depending on how you set up your user account.

Getting font metrics without GUI (console mode)

Let's say some images have to be generated by a Qt console program and that font metrics are needed by internal algorithms (they use the text width/height as input to compute the position where the drawing should occur). This program has to be runable on a Linux without any GUI (runlevel-3, basically a cluster without any display server).
Problem: QFontMetrics are only available when running a Qt application in GUI mode.
Any workaround to get string metrics without any display server ?
Ok after additional comments I think I understand your problem.
Just do it like that:
include <QApplication>
int main(int argv, char **args)
{
QApplication app(argv, args);
QApplication::processEvents(); // this should allow `QApplication` to complete its initialization
// do here whatever you need
return 0; // or some other value to report errors
}
You can also try use QGuiApplication this version doesn't require (doesn't use) widgets.
See also example in documentation how to handle none gui cases.
This code works perfectly on my Ubnutu with Qt 5.3
#include <QGuiApplication>
#include <QFontMetrics>
#include <QDebug>
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
QFont font("Times", 10, QFont::Bold);
qDebug() << font;
QFontMetrics metrics(font);
qDebug() << metrics.boundingRect("test");
return 0;
}
It also works with Qt 4.8 when QApplication is used.
Project file was quite simple
QT += core
TARGET = MetricsNoGui
TEMPLATE = app
SOURCES += main.cpp
Qt 4.8 has such QApplication constructor, whose 3rd parameter can help to solve the issue. Simple provide false as 3rd argument and enjoy using QFontMetrics in Qt console application. There will be no crashes if one starts app on systems without X server.
I didn't find a way to use QFont or QPrinter with QCoreApplication :( However, if you are able to install Xvfb, then your QApplication will be runnable also on a server without any display. I'm using this setup on a headless Raspberry Pi Zero.
Xvfb :1 -screen 0 1024x768x16 &
export DISPLAY=:1.0
./YourQApplication
This isn't the most elegant solution, but after hours of desperate searching, it's the only one I found.

Resources