How to remove console window on the start? - visual-studio

On the app start i have a console window, so how not to show it?
(Without Using WinMain! Because its parameters don't match to QApp)
My main.cpp code is:
int main(int _nArgCount, char * _pArgValues[]) {
QApplication app(_nArgCount, _pArgValues);
//QMLblock
QString strQmlPath = "qrc:qml/main.qml";
QQmlApplicationEngine engine;
QQmlComponent component(&engine, QUrl(strQmlPath));
if (component.status() == QQmlComponent::Error) {
qDebug()<<"Error:"<<component.errorString();
return app.exec();
}
Gui gui(component);
gui.recreateGui();
//state machine block
QStateMachine machine;
....
....
....
return app.exec();
}

Related

How to avoid bringing QMainWindow to the front when clicking on independent QWidget

I am working on Qt app. There I have QMainWindow and QWidget which is displayed independently and out of the window.
I want to achieve that if I click on that QWidget, the window doesn't come to the front. I.e if it is behind another app, it should remain like that.
I have created test app:
main.cpp
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow w;
w.show();
Widget mywidget;
return app.exec();
}
Widget.cpp
namespace
{
Qt::WindowFlags defaultWindowFlags()
{
Qt::WindowFlags f = 0;
f |= Qt::X11BypassWindowManagerHint;
f |= Qt::FramelessWindowHint;
f |= Qt::WindowStaysOnTopHint;
f |= Qt::CustomizeWindowHint;
f |= Qt::WindowDoesNotAcceptFocus;
f |= Qt::Window;
return f;
}
}
Widget::Widget(QWidget *parent) : QWidget(parent, defaultWindowFlags())
{
setFixedSize(100,100);
setStyleSheet("background-color:blue;");
move(56,89);
setVisible(true);
}
Leave out the line f |= Qt::WindowDoesNotAcceptFocus;, this makes Qt keep the focus at the main window.

Textarea slow for logging

I have a Qt application and I'd like to show some log. I use a TextArea. However, if the log is large or the events come too fast the GUI can't draw Textarea fast enough.
I have analyzed this problem with Qt Creator (QML Profiler) and if the log is large it takes 300 ms to draw the GUI. I use this software on a Raspberry Pi2.
Any ideas how to solve this? Should I use other QML controls? Thanks.
QML code:
TextArea {
text: appHandler.rawCommunication
readOnly: true
}
C++ code:
Q_PROPERTY(QString rawCommunication READ rawCommunication WRITE setrawCommunication NOTIFY rawCommunicationChanged)
void setrawCommunication(QString val)
{
val.append("\n");
val.append(m_rawCommunication);
m_rawCommunication = val;
emit rawCommunicationChanged(m_rawCommunication);
}
Use a view, like ListView. They instantiate their delegates as needed, based on which data the view says it needs to show depending on the position the user is at in the list. This means that they perform much better for visualising large amounts of data than items like TextArea, which in your case is going to keep a massive, ever-growing string in memory.
Your delegate could then be a TextArea, so you'd have one editable block of text per log line. However, if you don't need styling, I'd recommend going with something a bit lighter, like TextEdit. Taking it one step further: if you don't need editable text, use plain old Text. Switching to these might not make much of a difference, but if you're still seeing slowness (and have lots of delegates visible at a time), it's worth a try.
I tried the ListView suggestion but it has several drawbacks:
No easy way to keep the view positioned at the bottom when new output is added
No selection across lines/delegates
So I ended up using a cached TextArea, updating once every second:
TextArea {
id: outputArea_text
wrapMode: TextArea.Wrap
readOnly: true
font.family: "Ubuntu Mono, times"
function appendText(text){
logCache += text + "\n";
update_timer.start();
}
property string logCache: ""
Timer {
id: update_timer
// Update every second
interval: 1000
running: false
repeat: false
onTriggered: {
outputArea_text.append(outputArea_text.logCache);
outputArea_text.logCache = "";
}
}
Component.onCompleted: {
my_signal.connect(outputArea_text.appendText)
}
}
try this approach:
create a c++ logger class
append all logs to this class
and print them using some action, example a button click
this will solve your performance issue
Example of code:
Logger.h
#ifndef LOGGER_H
#define LOGGER_H
#include <QQmlContext>
#include <QObject>
#include <QStringList>
#include <QQmlEngine>
#include <QString>
#include <QtCore>
#include <QDebug>
class Logger : public QObject
{
Q_OBJECT
public:
explicit Logger(QObject *parent = 0);
~Logger();
Q_INVOKABLE QStringList *getLogStream();
Q_INVOKABLE void printLogStream();
Q_INVOKABLE void appendLog(QString log);
Q_INVOKABLE void log(QString log="");
Q_INVOKABLE void log(QString fileName, QString log);
signals:
public slots:
private:
QStringList* stringStream_;
};
#endif // LOGGER_H
Logger.cpp
#include "logger.h"
Logger::Logger(QObject *parent) :
QObject(parent),
stringStream_(new QStringList)
{
}
~Logger(){
if(stringStream_ != NULL)
{
delete stringStream_;
stringStream_ = NULL;
}
}
QStringList* Logger::getLogStream(){
return stringStream_;
}
void Logger::printLogStream()
{
QStringListIterator itr(*stringStream_);
while (itr.hasNext())
qDebug()<< itr.next()<<"\n";
}
void Logger::appendLog(QString log){
stringStream_->push_back(log) ;
}
void Logger::log(QString fileName,QString log)
{
#ifdef ENABLElogs
fileName.push_front(" [");
if(!fileName.contains(".qml"))
{
fileName.append(".qml]:");
}
qDebug()<<fileName<<log;
#else
Q_UNUSED(log);
Q_UNUSED(fileName);
#endif
}
void Logger::log(QString log)
{
#ifdef ENABLElogs
qDebug()<<log;
#else
Q_UNUSED(log);
#endif
}
main.cpp
#include <QtGui/QGuiApplication>
#include "qtquick2applicationviewer.h"
#include "logger.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer *viewer = new QtQuick2ApplicationViewer;
Logger* stream = new Logger;
viewer->rootContext()->setContextProperty("Stream",stream);
viewer->setMainQmlFile(QStringLiteral("qml/project/main.qml"));
viewer->showExpanded();
return app.exec();
}
main.qml
import QtQuick 2.0
import QtQuick.Controls 1.1
Rectangle {
width: 800
height: 480
Text {
text: qsTr("Hello World")
anchors.centerIn: parent
Component.onCompleted: Stream.appendLog("Text object is completed")
}
Column{
x:300
Button{
text:"append"
onClicked: {
Stream.appendLog("MouseArea object clicked")
}
Component.onCompleted: Stream.appendLog("Button object is completed")
}
Button{
text:"logger"
onClicked: {
Stream.printLogStream()
}
Component.onCompleted: Stream.appendLog("Button logger object is completed")
}
}
TextArea{
text:"blablabla"
Component.onCompleted: Stream.appendLog("TextArea object is completed")
}
Component.onCompleted: Stream.appendLog("the main object is completed")
}
project.pro
#add this line
# comment it, run qmake and recompile to disable logs
DEFINES += ENABLElogs
using this approch you can stop all logs with a single line change when you want to release your soft
However, I have included complete code, using "QAbstractListModel" for a Logging heavy data to QML
listmodel.h
#ifndef LISTMODEL_H
#define LISTMODEL_H
#include <QAbstractListModel>
class ListModel: public QAbstractListModel
{
Q_OBJECT
public:
ListModel();
// Q_PROPERTY(QStringList logs READ name WRITE nameChanged)
int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
Q_INVOKABLE QVariant activate(int i);
private:
QStringList m_list;
};
#endif // LISTMODEL_H
listmodel.cpp
#include "listmodel.h"
#include <QFile>
#include <QHash>
ListModel::ListModel()
{
QFile file("/home/ashif/LogFile");
if(!file.open(QIODevice::ReadOnly))
{
qDebug( "Log file open failed" );
}
bool isContinue = true;
do
{
if(file.atEnd())
{
isContinue = false;
}
m_list.append(file.readLine());
}
while( isContinue);
}
int ListModel::rowCount(const QModelIndex & parent ) const
{
return m_list.count();
}
QVariant ListModel::data(const QModelIndex & index, int role ) const
{
if(!index.isValid()) {
return QVariant("temp");
}
return m_list.value(index.row());
}
QVariant ListModel::activate(int i)
{
return m_list[i];
}
main.qml
import QtQuick 2.3
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
Window {
visible: true
ListView
{
width: 200; height: 250
anchors.centerIn: parent
model:mylistModel
delegate: Text
{
text:mylistModel.activate(index)
}
}
}
main.cpp
#include <QGuiApplication>
#include <QQmlContext>
#include <QQmlApplicationEngine>
#include "logger.h"
#include "listmodel.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
Logger myLogger;
ListModel listModel;
engine.rootContext()->setContextProperty("mylistModel", &listModel);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}

Transient scrollbar in Qt

I want to use transient scrollbar (Transient scroll bars appear when the content is scrolled and disappear when they are no longer needed) in Qt application. For this purpose I have inheritanced class QproxyStyle and reimplemented function styleHint. Code placed below.
File ScrollBar.h:
#include <QStyle>
#include <QCommonStyle>
#include <QProxyStyle>
class ScrollBarStyle : public QProxyStyle
{
public:
int styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *widget, QStyleHintReturn *hret) const;
};
File ScrollBar.c:
#include "ScrollBar.h"
int ScrollBarStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *widget,QStyleHintReturn *hret) const
{
int ret = 0;
switch (sh) {
case SH_ScrollBar_Transient:
ret = true;
break;
default:
return QProxyStyle::styleHint(sh, opt, widget, hret);
}
return ret;
}
File MainWindow.h:
#include <QMainWindow>
#include <QTextEdit>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = 0);
~MainWindow();
};
File MainWindow.cpp:
#include <QTextEdit>
#include "MainWindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QTextEdit *l = new (std::nothrow) QTextEdit(this);
if (l == 0)
return;
setCentralWidget(l);
}
MainWindow::~MainWindow()
{
}
File main.cpp:
#include "ScrollBar.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
ScrollBarStyle *style = new (std::nothrow) ScrollBarStyle;
if(style == 0)
return -1;
style->setBaseStyle(a.style());
w.show();
return a.exec();
}
But I have got a problem: transient scrollbar has been appearing only once (when text doesn't fit in the text area) then it has been disappeared and never come back visible.
So how can I fix this problem?
Thanks!
You have forgotten to set the style to application.
a.setStyle(style);

glfwCreateWindow(..) returns null in Visual Studio

I am using the GLFW and only want to open a empty windows.
I downloaded the GLFW for Windows 32.
Created an empty console project and wrote this code:
#include "main.h"
#pragma comment (lib, "glfw3dll")
#pragma comment (lib, "OpenGL32")
#define GLFW_DLL
#include <glfw3.h>
#include <chrono>
#include <iostream>
using namespace std::chrono;
GLFWwindow* window;
bool running = true;
bool initialise(){
return true;
}
void update(double deltaTime){
}
void render(){
}
int main(int argc, char **argv) {
if (!glfwInit)
return -1;
window = (glfwCreateWindow(800, 600, "Hello World", nullptr, nullptr));
if (window == nullptr){
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
if (!initialise()){
glfwTerminate();
return -1;
}
auto currentTimeStamp = system_clock::now();
auto prevTimeStamp = system_clock::now();
while (running)
{
currentTimeStamp = system_clock::now();
auto elapsed = duration_cast<milliseconds>(currentTimeStamp - prevTimeStamp);
auto seconds = double(elapsed.count()) / 1000.0;
update(seconds);
render();
glfwPollEvents();
prevTimeStamp = currentTimeStamp;
}
glfwTerminate();
return -1;
}
And I think I added the library and the header correctly.
But everytime the programm exits with -1 after the glfwCreateWindow(..) function, because this functions return null.
Can somebody help me?
if (!glfwInit)
return -1;
I'm not sure why glfwInit would be NULL unless something truly terrible happened during DLL load.
Try calling glfwInit() instead:
if( !glfwInit() )
return -1;

How to view qDebug() in Visual Studio?

In Qt Creator, I could view the qDebug(), qWarning() etc. output directly in the IDE. How could I do this in Visual Studio?
There is an easier way:
Go to Project Properties > Linker > System : set SubSystem to "SUBSYSTEM:CONSOLE"
You will now get a console when you run your program and qDebug() will be redirected to it. (You can also use std::cout)
When you run the program with an attached debugger, it will show in the Output Window of Visual Studio, but for Debug purposes i often redirect the debug output to some kind of nice log window, which you can do by using the function qInstallMsgHandler:
the code that i use:
#include <qapplication.h>
#include <qwidget.h>
#include <qplaintextedit.h>
#include <qmetaobject.h>
#include <qthread.h>
#include <qboxlayout.h>
#include <qdatetime.h>
#include <qdebug.h>
#include <cstdio>
#include <cassert>
QWidget *DEBUG_MESSAGE_DISPLAY_WIDGET = NULL;
QPlainTextEdit *DEBUG_MESSAGE_DISPLAY_TEXTEDIT = NULL;
void setupDebugDisplay();
void debugMessageDisplayFunc(QtMsgType type, const char *msg);
int main( int argc, char* argv[] )
{
QApplication a( argc, argv );
a.setQuitOnLastWindowClosed( true );
setupDebugDisplay();
// your code here.... e.g:
// YourMainWindow mainWindow;
int ret = a.exec();
delete DEBUG_MESSAGE_DISPLAY_WIDGET;
return ret;
}
void setupDebugDisplay()
{
QWidget *widget = new QWidget();
widget->setWindowTitle( "Debug Log" );
widget->setAttribute( Qt::WA_QuitOnClose, false ); //quit only when mainwindow is closed
QBoxLayout* layout = new QVBoxLayout();
widget->setLayout( layout );
QPlainTextEdit *textEdit = new QPlainTextEdit( widget );
QFont font = QFont( "Monospace" );
font.setStyleHint(QFont::TypeWriter);
textEdit->setFont( font );
textEdit->setReadOnly(true);
layout->addWidget( textEdit );
widget->show();
DEBUG_MESSAGE_DISPLAY_WIDGET = widget;
DEBUG_MESSAGE_DISPLAY_TEXTEDIT = textEdit;
qInstallMsgHandler(debugMessageDisplayFunc);
}
void debugMessageDisplayFunc(QtMsgType type, const char *msg)
{
bool do_abort = false;
const char* msgTypeStr = NULL;
switch (type) {
case QtDebugMsg:
msgTypeStr = "Debug";
break;
case QtWarningMsg:
msgTypeStr = "Warning";
break;
case QtCriticalMsg:
msgTypeStr = "Critical";
break;
case QtFatalMsg:
msgTypeStr = "Fatal";
do_abort = true;
default:
assert(0);
return;
}
QTime now = QTime::currentTime();
QString formattedMessage =
QString::fromLatin1("%1 %2 %3")
.arg(now.toString("hh:mm:ss:zzz"))
.arg(msgTypeStr).arg(msg);
// print on console:
fprintf( stderr, "%s\n", formattedMessage.toLocal8Bit().constData() );
// print in debug log window
{
bool isMainThread = QThread::currentThread() == QApplication::instance()->thread();
if(DEBUG_MESSAGE_DISPLAY_TEXTEDIT)
{
if( isMainThread )
DEBUG_MESSAGE_DISPLAY_TEXTEDIT->appendPlainText( formattedMessage );
else // additional code, so that qDebug calls in threads will work aswell
QMetaObject::invokeMethod( DEBUG_MESSAGE_DISPLAY_TEXTEDIT, "appendPlainText", Qt::QueuedConnection, Q_ARG( QString, formattedMessage ) );
}
}
}
It redirect to Output windows of visual studio.
You may as well use DebugView++ for QDebug it still works with it
https://github.com/CobaltFusion/DebugViewPP
OutputDebugString is key to do that.
How I do with Qt 5.15:
#if defined(Q_OS_WIN) && defined(QT_DEBUG)
qInstallMessageHandler([](QtMsgType type, const QMessageLogContext &ctx, const QString &message) {
const QString msg = qFormatLogMessage(type, ctx, message);
// write logs to Output window of Visual Studio
{
QString prefix;
switch (type) {
case QtWarningMsg:
prefix = "[WARNING] ";
break;
case QtCriticalMsg:
prefix = "[CRITICAL ERROR] ";
break;
case QtFatalMsg:
prefix = "[FATAL ERROR] ";
break;
}
auto msgW = QString(prefix + message).toStdWString();
msgW.append(L"\n");
OutputDebugString(msgW.c_str());
}
});
#endif

Resources