Error endl was not declared in this scope

Ошибка при компиляции error: 'endl' was not declared in this scope C++ Решение и ответ на вопрос 2248144

_Electric_

0 / 0 / 1

Регистрация: 24.03.2018

Сообщений: 29

1

17.05.2018, 22:03. Показов 14334. Ответов 4

Метки нет (Все метки)


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <conio.h>
void main()
{
    double a, b, x, h, r, s;
    int n, zn = -1, k;
    puts("Input a,b,h,n");
    endl;
    scanf("%lf%lf%lf%d", &a, &b, &h, &n);
    for (x=a; x<=b; x+=h) {
        r = s = 1;
        for (k = 1; k <= n; k++) {
            r = zn * r * x / k;
            s += r;
        }
        printf("n x=%8.2lf sum=%8.5lf", x, s);
    }
    puts("nPress any key...");
    endl;
    getch();
    }

Выводит следующее на консоль:

«C:Program FilesJetBrainsCLion 2017.3.3bincmakebincmake.exe» —build C:UsersSanekCLionProjectslaba_teenuntitledcm ake-build-debug —target all — -j 4
Scanning dependencies of target untitled
[ 50%] Building CXX object CMakeFiles/untitled.dir/main.cpp.obj
C:UsersSanekCLionProjectslaba_teenuntitledma in.cpp:3:11: error: ‘::main’ must return ‘int’
void main()
^
C:UsersSanekCLionProjectslaba_teenuntitledma in.cpp: In function ‘int main()’:
C:UsersSanekCLionProjectslaba_teenuntitledma in.cpp:8:5: error: ‘endl’ was not declared in this scope
endl;
^~~~
C:UsersSanekCLionProjectslaba_teenuntitledma in.cpp:8:5: note: suggested alternative: ‘enum’
endl;
^~~~
enum
mingw32-make.exe[2]: *** [CMakeFilesuntitled.dirbuild.make:62: CMakeFiles/untitled.dir/main.cpp.obj] Error 1
mingw32-make.exe[1]: *** [CMakeFilesMakefile2:67: CMakeFiles/untitled.dir/all] Error 2
mingw32-make.exe: *** [Makefile:83: all] Error 2

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



panuchi

5 / 5 / 2

Регистрация: 13.03.2017

Сообщений: 101

17.05.2018, 22:06

2

_Electric_,

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <conio.h>
void main()
{
    double a, b, x, h, r, s;
    int n, zn = -1, k;
    puts("Input a,b,h,nn");
    scanf("%lf%lf%lf%d", &a, &b, &h, &n);
    for (x=a; x<=b; x+=h) {
        r = s = 1;
        for (k = 1; k <= n; k++) {
            r = zn * r * x / k;
            s += r;
        }
        printf("n x=%8.2lf sum=%8.5lf", x, s);
    }
    puts("nPress any key...n");
    getch();
    }



0



0 / 0 / 1

Регистрация: 24.03.2018

Сообщений: 29

18.05.2018, 06:30

 [ТС]

3

Теперь новая ошибка

«C:Program FilesJetBrainsCLion 2017.3.3bincmakebincmake.exe» —build C:UsersSanekCLionProjectslaba_teenuntitledcm ake-build-debug —target all — -j 4
Scanning dependencies of target untitled
[ 50%] Building CXX object CMakeFiles/untitled.dir/main.cpp.obj
C:UsersSanekCLionProjectslaba_teenuntitledma in.cpp:3:11: error: ‘::main’ must return ‘int’
void main()
^
mingw32-make.exe[2]: *** [CMakeFilesuntitled.dirbuild.make:62: CMakeFiles/untitled.dir/main.cpp.obj] Error 1
mingw32-make.exe[1]: *** [CMakeFilesMakefile2:67: CMakeFiles/untitled.dir/all] Error 2
mingw32-make.exe: *** [Makefile:83: all] Error 2



0



LegionK

391 / 259 / 194

Регистрация: 02.05.2017

Сообщений: 1,003

18.05.2018, 07:07

4

Лучший ответ Сообщение было отмечено _Electric_ как решение

Решение

C++
1
#include <iostream> //вместо 1 строчки

+

C++
1
cout << std::endl  // его выводить надо, а не просто вызвать

и

C++
1
int main()

+

C++
1
return 0 //в конце мэйна



2



0 / 0 / 1

Регистрация: 24.03.2018

Сообщений: 29

18.05.2018, 22:50

 [ТС]

5

Спасибо, помогло



0



I have listed my code below. I get soooo many errors saying cout and endl was not declared in this scope. I do not know what I am doing wrong or how to force the class to recognise cout? I hope I am explaining my problem correctly. If I comment out the methods (not the constructor) it works. I am probably just making a novice mistake here — please help.

using namespace std;

class SignatureDemo{
public:
    SignatureDemo (int val):m_Val(val){}
    void demo(int n){
        cout<<++m_Val<<"tdemo(int)"<<endl;
    }
    void demo(int n)const{
        cout<<m_Val<<"tdemo(int) const"<<endl;
    }
    void demo(short s){
        cout<<++m_Val<<"tdemo(short)"<<endl;
    }
    void demo(float f){
        cout<<++m_Val<<"tdemo(float)"<<endl;
    }
    void demo(float f) const{
        cout<<m_Val<<"tdemo(float) const"<<endl;
    }
    void demo(double d){
        cout<<++m_Val<<"tdemo(double)"<<endl;
    }

private:
    int m_Val;
};



int main()
{
    SignatureDemo sd(5);
    return 0;
}

n. m.'s user avatar

n. m.

109k14 gold badges127 silver badges236 bronze badges

asked Oct 12, 2013 at 7:12

user2873416's user avatar

3

The compiler needs to know where to find std::cout first. You just need to include the correct header file:

#include <iostream>

I’d suggest you not to pollute the namespace using using directives. Instead either learn to prefix std classes/objects with std:: or use specific using directives:

using std::cout;
using std::endl;

answered Oct 12, 2013 at 14:01

Shoe's user avatar

ShoeShoe

74.1k35 gold badges166 silver badges268 bronze badges

  • Forum
  • UNIX/Linux Programming
  • cin,cout,and endl of c++

cin,cout,and endl of c++

Hi,
Dear everybody,I write a program,it includes followed head files:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <fstream.h>
#include <math.h>

But,when I compile it,screen out:
error: `cout’ was not declared in this scope
error: `endl’ was not declared in this scope
error: `cin’ was not declared in this scope
Could please youtell me how can I do,thank you.
wenli wang
th26,August,2010

Add:

1
2
#include <iostream>
using namespace std;

In addition, <fstream.h> is deprecated. Use <fstream> instead. You should also use <cstring>, <cstdio>, <cstdlib> and <cmath> instead of the C (.h) variants.

I recommend that you avoid «using namespace std;» if you can avoid it. Prefer to use «std::cin», «std::cout» and «std::endl» instead. It’s a bad habit that many programmers learn in school that they struggle to break as a professional programmer.

If I can ask, why is that a bad habit?

It’s a bad habit because it’s incorrect. All C++ standard headers (including those from the C library) have no .h suffix. I would assume this is to separate standard headers from user-created/non-standard ones (e.g. the Windows and POSIX APIs)

Ok, but I mean the namespace thing :p

Oh; there are several reasons for that. One of them has to do with name conflicts.

I’d break that habit ASAP, I did; it really isn’t difficult to prefix «std::» to things.

ok..I’ll have a look on google to find why :)

Using namespaces globally is not a bad habit, imo. When creating applications that only use the STL, the C library and standard C++ no naming conflicts should emerge. I do, however agree that you should not make a habit of it. Be wary of the effect of (using) namespaces, so that when things go (horribly) wrong you know what to do.

Is it worth the risk? It probably takes more energy to «Be wary of the effect» than it does to type «std::» a few times.

Namespaces separate and organize functionality. You can have a «xander333::sort()» function and it won’t conflict with «std::sort()» or «boost::sort()» or any other sort(). Without namespaces their can be only one sort().

Now let’s say you’ve put «using namespace std;» in all your source files and you’ve implemented a simple templated function called «fill()» in the global namespace of one of your files. This file also depends on a header from libFoo — «foo.hpp». Version 2.1 of libFoo comes out and all of a sudden your program no longer compiles. You version of «fill()» suddenly conflicts with another «fill()»! What happened???

It turns out that the folks implementing libFoo included <algorithm> in the new version of «foo.hpp» when they didn’t before. Now you have all of the standard algorithms being included in your source file, and your «using namespace std;» has pulled them all into the global namespace. std::fill() now directly conflicts with your fill().

More insidious, you’ve gotten your code to compile by renaming your fill() to xander333_fill(), but something’s not working right — your report numbers are off. It turns out that your custom divides() function, which does fixed precision math, is no longer being called because the templated function from <functional> (also newly included by «foo.hpp») makes for a better match because you’re calling types did not exactly match the declared types.

I try to compile it again using methods given by Kyon and PanGalactic,but fail.I think may be the LD_LIBRARY_PATH environment variables is wrong and computer can not find the head files.I do this in redhat linux enterprise4.8(gnu gcc 3.2.3 or latter)
g++ plot_fitsfile.cc -I/usr/include
But out again:
error: `cout’ was not declared in this scope
error: `endl’ was not declared in this scope
error: `cin’ was not declared in this scope
What should I do?Thank you.

Last edited on

Use std::cout, std::cin, and std::endl.

chrisname wrote:
Is it worth the risk? It probably takes more energy to «Be wary of the effect» than it does to type «std::» a few times.

By «Be wary of the effect» I mean, know what namespaces actually do. Which is slight renaming. Either stating using «using namespace std;» or use «std::..» only are wrong. I personally don’t like using things I don’t know about.

@Wengli Wang: What’s the code you are trying to compile, in it’s full extends?

you will, in time come across occasions when you get name clashes.
then you will understand, grasshopper.

it’s OK for trivial stuff I’d say

Mr Kyon,The length of code is bigger than max length and can’t post here.Could please you send your email address to china.wenli.wang@gmail.com.I will send the codes to you,and please you give me some advice for compile it.Thank you.

mr kyon thanks U so much cause I’l be learn c++ brginner on linux……..

Topic archived. No new replies allowed.

  • Home
  • Forum
  • Qt
  • Newbie
  • endl’ was not declared in this scope

  1. Default endl’ was not declared in this scope

    whats the problem here… it makes me angryy!!!!
    i face with this error

    » ‘endl’ was not declared in this scope»

    here is the code

    1. #include "mainwindow.h"

    2. #include "ui_mainwindow.h"

    3. #include <QFile>

    4. #include <iostream>

    5. MainWindow::MainWindow(QWidget *parent) :

    6. ui(new Ui::MainWindow)

    7. {

    8. ui->setupUi(this);

    9. }

    10. MainWindow::~MainWindow()

    11. {

    12. delete ui;

    13. }

    14. void MainWindow::on_pushButton_clicked()

    15. {

    16. QFile myFile("c://Victory.txt");

    17. ds<<"bbbb/n"<<endl;

    18. myFile.close();

    19. }

    To copy to clipboard, switch view to plain text mode 

    Last edited by wysota; 20th June 2012 at 11:20.

    Reason: missing [code] tags


  2. Default Re: endl’ was not declared in this scope

    Please use [code] and [/code] tags around your code in future. You could even edit the post above to add them.

    The error message is exactly what it says, the name «endl» has not been declared. If you meant std::endl then you have to say so (or use the using keyword). This is basic C++ and nothing at all to do with Qt.

    It won’t compile either way because there is no QDataStream operator<<() suitable for std::endl. Even if it did compile I suspect it would not do what you are expecting because QDataStream is not a good mechanism for writing a text file. Perhaps you wanted QTextStream, which does have an associated endl() function (unrelated to std::endl).


  3. Default Re: endl’ was not declared in this scope

    use «n» (carriage return)
    for Ex:

    1. ds<<"bbbbn";

    To copy to clipboard, switch view to plain text mode 

    Life is about making the right decisions and moving on.


  4. Default Re: endl’ was not declared in this scope

    mention this after the header file declaration:—->

    1. using namespace std;

    To copy to clipboard, switch view to plain text mode 


  5. Default Re: endl’ was not declared in this scope

    Ali Reza, while doing as you suggest (and dropping the std::endl) will make the code compile, it will still not do what the OP expects it to do. QDataStream is the wrong tool for the job of writing a text file… the output file will have these bytes written (using C-style escapes):

    1. 0 0 0 06 b b b b n 0

    To copy to clipboard, switch view to plain text mode 

    That is, it is a ten-byte binary file rather than a five-byte (or six on Windows) text file.

    Sonulohani, this will not help. The code will still fail to compile, just for different reasons.


  6. Default Re: endl’ was not declared in this scope

    @ Chris
    i don’t understand your mean.
    ‘n’ take 1 byte of a file, why this wrong??
    ‘n’ is a ASCII code and all ASCII codes take 1 byte (7 bit data and 1 bit zero)
    if those is not correct tell me why ??
    thanks dear Chris

    Life is about making the right decisions and moving on.


  7. Default Re: endl’ was not declared in this scope

    Quote Originally Posted by Ali Reza
    View Post

    @ Chris
    i don’t understand your mean.
    ‘n’ take 1 byte of a file, why this wrong??
    ‘n’ is a ASCII code and all ASCII codes take 1 byte (7 bit data and 1 bit zero)
    if those is not correct tell me why ??

    Why don’t you just try your code and see how many bytes the file generated with it has.

    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  8. Default Re: endl’ was not declared in this scope

    The character ‘n’ is a single byte, correct. I didn’t say it wasn’t.

    This operation is not on single characters, it is on the nul-terminated C-string «bbbbn» with the intent of writing text to a file. In memory that string occupies 6 bytes, the 6th being a nul terminator (»).

    When a string of characters (i.e const char*) is streamed to a QDataStream the result is preceded by the length of the string, including the nul terminating byte, as a 32-bit integer then the bytes of the string including the nul terminator. You end up with 4 + 6 = 10 bytes in the file, some of which are non-printable. See my last post for the ten bytes in detail.

    The original poster almost certainly wants a plain text file, and QDataStream does not provide that. QTextStream, as the name suggests, is for manipulating text streams. When streamed to a QTextStream the string «bbbbn» will result in the expected 5 or 6 bytes in the text file. If the underlying file is opened with the QIODevice::Text option:

    1. }

    To copy to clipboard, switch view to plain text mode 

    then line-ending conversions may happen just as with the standard C/C++ library. On Windows machines the single ‘n’ in the original string will be output as the two character pair «rn» leading to a six byte file «bbbbrn».


  9. Default Re: endl’ was not declared in this scope

    yeah i got it
    thanks very much

    Life is about making the right decisions and moving on.


Similar Threads

  1. Replies: 6

    Last Post: 26th June 2011, 08:15

  2. Replies: 5

    Last Post: 19th March 2011, 09:58

  3. Replies: 2

    Last Post: 18th November 2009, 15:36

  4. Replies: 5

    Last Post: 25th August 2009, 10:43

  5. Replies: 2

    Last Post: 28th December 2007, 19:30

Bookmarks

Bookmarks


Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
  • BB code is On
  • Smilies are On
  • [IMG] code is On
  • [VIDEO] code is On
  • HTML code is Off

Forum Rules

Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.


0

0

После Vim и Kate решил попробовать какую-нибудь приличную IDE. Выбор пал на сабж. После создания проект «Hello World C++ Project» отказался компилиться, сославшись на

g++ -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/kr7.d" -MT"src/kr7.d" -o"src/kr7.o" "../src/kr7.cpp"
../src/kr7.cpp:9:20: warning: iostream: No such file or directory
../src/kr7.cpp: In function 'int main()':
../src/kr7.cpp:13: error: 'cout' was not declared in this scope
../src/kr7.cpp:13: error: 'endl' was not declared in this scope

В свойствах проекта я явно указал в include paths строчку /usr/include/c++/4.3.3/ , но ошибки полезли из стандартных хеадеров:

g++ -I/usr/include/c++/4.3.3 -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/kr7.d" -MT"src/kr7.d" -o"src/kr7.o" "../src/kr7.cpp"
In file included from /usr/include/c++/4.3.3/iosfwd:46,
                 from /usr/include/c++/4.3.3/ios:44,
                 from /usr/include/c++/4.3.3/ostream:45,
                 from /usr/include/c++/4.3.3/iostream:45,
                 from ../src/kr7.cpp:9:
/usr/include/c++/4.3.3/bits/stringfwd.h:46: error: expected constructor, destructor, or type conversion before '(' token
/usr/include/c++/4.3.3/bits/stringfwd.h:55: error: expected type-specifier before 'allocator'
/usr/include/c++/4.3.3/bits/stringfwd.h:55: error: expected '>' before 'allocator'
/usr/include/c++/4.3.3/bits/stringfwd.h:60: error: template argument 3 is invalid
/usr/include/c++/4.3.3/bits/stringfwd.h:60: error: invalid type in declaration before ';' token
/usr/include/c++/4.3.3/bits/stringfwd.h:68: error: '_GLIBCXX_END_NAMESPACE' does not name a type
In file included from /usr/include/c++/4.3.3/cwchar:49,
                 from /usr/include/c++/4.3.3/bits/postypes.h:47,
                 from /usr/include/c++/4.3.3/iosfwd:47,
                 from /usr/include/c++/4.3.3/ios:44,
                 from /usr/include/c++/4.3.3/ostream:45,
                 from /usr/include/c++/4.3.3/iostream:45,
                 from ../src/kr7.cpp:9:
/usr/include/c++/4.3.3/cstddef:57: error: '::size_t' has not been declared
In file included from /usr/include/c++/4.3.3/bits/postypes.h:47,
                 from /usr/include/c++/4.3.3/iosfwd:47,
                 from /usr/include/c++/4.3.3/ios:44,
                 from /usr/include/c++/4.3.3/ostream:45,
                 from /usr/include/c++/4.3.3/iostream:45,
                 from ../src/kr7.cpp:9:
/usr/include/c++/4.3.3/cwchar:61: error: expected constructor, destructor, or type conversion before 'extern'
In file included from /usr/include/c++/4.3.3/ios:45,
                 from /usr/include/c++/4.3.3/ostream:45,
                 from /usr/include/c++/4.3.3/iostream:45,
                 from ../src/kr7.cpp:9:
/usr/include/c++/4.3.3/exception:40: error: expected declaration before end of line

Неужели у эклипса по умолчанию настолько неюзабельный конфиг, или я что-то делаю неправильно?

I have installed itpp-4.2.tar.gz and itpp-external-3.2.0.tar.gz in Ubuntu
10.04 , gcc/g++ version 4.4.3

and I write the same example as IT++ tutorial, URL: http://itpp.sourceforge.n
et/current/installation.html#localinst

I set the environment path as follows:


export LD_LIBRARY_PATH=»/home/docomo/soft/itpp-4.2/lib:$LD_LIBRARY_PATH»

export LDFLAGS=»-L/home/docomo/soft/itpp-4.2/lib

export CPPFLAGS=»-I/home/docomo/soft/itpp-4.2/include»


the Example codes:


include <itpp itsignal.h=»»>

using namespace itpp;

using namespace std;

int main()

{

for (int i = 0; i < 10; i++) {

mat X = randn(500, 500);

mat Z = chol(X * X.transpose());

cout << Z(0, 0) << endl;

}

for (int i = 0; i < 10; i++) {

cvec a = fft(randn_c(10000));

cout << a(5) << endl;

}

it_assert_debug(1 == 0, «Debugging is on!»);

}

——Makefile——

FLAGS_DEBUG=’/home/docomo/soft/itpp-4.2/bin/itpp-config —debug —cflags’

FLAGS_OPT=’/home/docomo/soft/itpp-4.2/bin/itpp-config —cflags’

LIBS_DEBUG=’/home/docomo/soft/itpp-4.2/bin/itpp-config —debug —static
—libs’

LIBS_OPT=’/home/docomo/soft/itpp-4.2/bin/itpp-config —static —libs’

itpptest:itpptest.cpp

g++ $(FLAGS_DEBUG) itpptest.cpp -o itpptest_debug $(LIBS_DEBUG)

g++ $(FLAGS_OPT) itpptest.cpp -o itpptest_opt $(LIBS_OPT)


After i execute ‘make’ command, the Error happened:

—-Error info as follows————
root@docomo10:/home/docomo/testcode# make

g++ ‘/home/docomo/soft/itpp-4.2/bin/itpp-config —debug —cflags’ itpptest.cpp
-o itpptest_debug ‘/home/docomo/soft/itpp-4.2/bin/itpp-config —debug —static
—libs’

g++: /home/docomo/soft/itpp-4.2/bin/itpp-config —debug —cflags: No such file
or directory

g++: /home/docomo/soft/itpp-4.2/bin/itpp-config —debug —static —libs: No
such file or directory

itpptest.cpp:4:27: error: itpp/itsignal.h: No such file or directory

itpptest.cpp:5: error: ‘itpp’ is not a namespace-name

itpptest.cpp:5: error: expected namespace-name before ‘;’ token

itpptest.cpp: In function ‘int main()’:

itpptest.cpp:12: error: ‘mat’ was not declared in this scope

itpptest.cpp:12: error: expected ‘;’ before ‘x’

itpptest.cpp:13: error: expected ‘;’ before ‘z’

itpptest.cpp:14: error: ‘cout’ was not declared in this scope

itpptest.cpp:14: error: ‘z’ was not declared in this scope

itpptest.cpp:14: error: ‘endl’ was not declared in this scope

itpptest.cpp:18: error: ‘cvec’ was not declared in this scope

itpptest.cpp:18: error: expected ‘;’ before ‘a’

itpptest.cpp:19: error: ‘cout’ was not declared in this scope

itpptest.cpp:19: error: ‘a’ was not declared in this scope

itpptest.cpp:19: error: ‘endl’ was not declared in this scope

itpptest.cpp:22: error: ‘it_assert_debug’ was not declared in this scope

make: *** Error 1


Could you help me to solve this problem?

September 2021 saw the launch of Qt 6.2 – the first Qt 6 version with feature parity to Qt 5.15. I wanted to find out whether Qt 6.2 is fit for products. So, I migrated the HMI application of the ROPA sugar beet harvesters from Qt 5.12 over Qt 5.15 to Qt 6.2. The migration went very smooth and quick. And yes, Qt 6.2 is fit for products!

Introduction

The migration to Qt 6 is my 5th Qt migration. The migrations from Qt 1 to Qt 2, from Qt 2 to Qt 3 and from Qt 4 to Qt 5 were fairly smooth. The migration of an IDE for formal verification and of the driver terminal of a forage harvester were a matter of 2-3 days. The migration from Qt 3 to Qt 4 was extremely painful. Migrating an IDE for Bluetooth development took me 6 months.

I was curious how long I would need to migrate the driver terminal of a sugar beet harvester from Qt 5.12 to Qt 6.2. The driver terminal has 350 source files (.cpp, .h, .qml) with 50K lines of hand-written code. It also has 45 source files with 74K lines of generated code for the terminal-machine communication.

The guide Porting to Qt 6 from the official Qt documentation is the starting point for the migration. It suggests to port the application to Qt 5.15 in a first step and to Qt 6.2 in a second step. The Qt developers made the APIs of Qt 5.15 as similar as possible to the APIs of Qt 6.2 to reduce the migration efforts.

I’ll describe step by step how to change the CMake files, how to fix the warnings and errors flagged by the C++ compiler, how to find the QML incompatibilities and how to set up the development environment for Qt 6.2.

Originally, I migrated the terminal application to Qt 6.0 in December 2020 – just after Qt 6.0 came out. Qt 6.0 and Qt 6.1 were not ready for product releases, because they lacked important modules like SerialBus, Multimedia, Charts, RemoteObjects and WebEngine. I had to to exclude some parts from the migration.

The Qt Project promised to fix these shortcomings with Qt 6.2 in autumn 2021 and they delivered. Excellent work! I decided to update my original post as well. The post now covers the migration from Qt 5.12 all the way to Qt 6.2. With Qt 6.2, I could include SerialBus and Multimedia. SerialBus with CAN worked right ouf the box. Multimedia required a straightforward rewrite for playing back MP3 files, because QMediaPlaylist was removed from Multimedia.

The migration of the harvester terminal from Qt 5.12 to Qt 6.2 took me two days. Writing this post took me longer. In October, I started to implement the driver terminal of a construction machine with Qt 6.2. I use Qt 6.2 for my FOSS compliance checker. Hence, I can recommend the use of Qt 6 in products!

The harvester application runs with Qt 5.12. We install Qt 5.15.2 and QtCreator 4.13 on our development PC. The PC should run Ubuntu 16.04 or newer.

C++ Compiler Warnings and Errors

The harvester application consists of three CMake projects: the executable Main, the library Hmi and the library Can. We switch on the deprecation warnings by adding the line

target_compile_definitions(${PROJECT_NAME} PUBLIC 
    "QT_DISABLE_DEPRECATED_BEFORE=0x050F00")

to the CMakeLists.txt of each project. This macro triggers a warning for every function that is deprecated in Qt 5.15 or older. Sometimes the use of a deprecated function causes an error. The next subsections list the C++ compiler warnings and errors I encountered while migrating the harvester application from Qt 5.12 to Qt 5.15.

The documentation page Obsolete Classes lists all the classes that may be removed in future releases and all the classes with functions that may be removed in future releases. The documentation often gives a hint how to replace an obsolete class or function.

Error/Warning: ‘endl’ is deprecated: Use Qt::endl

Problem:

QTextStream os(&dbFile);
os << QStringLiteral("[access]") << endl;

Most occurrences of endl triggered the warning: 'endl' is deprecated: Use Qt::endl. Some occurrences triggered an error: ‘endl’ was not declared in this scope. The compiler couldn’t distinguish between std::endl and Qt::endl.

Fix:

QTextStream os(&dbFile);
os << QStringLiteral("[access]") << Qt::endl;

We replace each occurrence of endl by Qt::endl. All stream manipulators are now prefixed with the Qt namespace: for example, Qt::hex, Qt::fixed, Qt::left and Qt::ws.

Error: ‘longMonthName’ is not a member of ‘QDate’

Problem:

return QDate::longMonthName(i, QDate::StandaloneFormat);

The static function QDate::longMonthName was removed from QDate.

Fix:

return QLocale().monthName(i);

The documentation of QDate::longMonthName hints at QLocale for a replacement. QLocale::monthName returns the long month name by default.

Error: no matching function for call to ‘QProcess::execute(const char [10])’

Problem:

QProcess::execute("/bin/sync");

The variant of QProcess::execute with the command as its only argument was removed.

Fix:

QProcess::execute("/bin/sync", {});

We must always use the two-argument variant, where the second argument is a QStringList with the options and arguments of the command. As sync doesn’t have any arguments or options, the second argument is the empty list.

Error: ‘mapped’ is not a member of ‘QSignalMapper’

Problem:

using MappedSignal = void(QSignalMapper::*)(int);
connect(&m_impl->m_signalMapper, 
        static_cast<MappedSignal>(&QSignalMapper::mapped),
        m_impl.data(),
        &DriverModel::Impl::onDriverChanged);

Before Qt 5.15, QSignalMapper::mapped had an overload for each of the four types of the single argument: QObject*, QWidget*, const QString& and int. We had to tell the compiler with a static_cast which overload to use in the connect statements. The overloads are obsolete in Qt 5.15.

Fix:

connect(&m_impl->m_signalMapper, &QSignalMapper::mappedInt,
        m_impl.data(), &DriverModel::Impl::onDriverChanged);

From Qt 5.15, the four overloads have different names mappedInt, mappedObject, mappedString and mappedWidget. This eliminates the cast and makes the code simpler.

Error: no member named ‘insertMulti’ in ‘QMap >’

Problem:

QMap<int, std::function<void()>> importCalls;
importCalls.insertMulti(0, [this, path](
    {m_customerModel.importCsvFile(path);});

Before Qt 5.15, QMap distinguished between maps and multi-maps by insert and insertMulti.

Fix:

QMultiMap<int, std::function<void()>> importCalls;
importCalls.insert(0, [this, path](
    {m_customerModel.importCsvFile(path);});

Qt 5.15 introduces a new class QMultiMap, which inherits from QMap. We insert elements into a QMultiMap with insert now.

Error/Warning: ‘QString::SplitBehavior’ has not been declared

Problem:

auto nameParts = customer->name()
    .split(' ', QString::SkipEmptyParts);

Like many other enum constants, QString::SkipEmptyParts was moved into the namespace Qt. The problem often occurs as a warning:

‘... QString::split ...’ is deprecated: Use Qt::SplitBehavior variant instead [-Wdeprecated-declarations]

Fix:

auto nameParts = customer->name()
    .split(' ', Qt::SkipEmptyParts);

The warning tells us what to do. We replace QString::SplitBehavior by Qt::SplitBehavior.

Error: call of overloaded ‘append()’ is ambiguous

Problem:

QVector<QPair<QString, QString>> m_counterCats;
m_counterCats.append({"Gesamt", ""});

QVector<T>::append has gained a third overload for rvalue references T&& in addition to the existing const T& and const QVector<T>&. The C++17 compiler cannot distinguish between these three overloads.

Fix:

QVector<QPair<QString, QString>> m_counterCats;
m_counterCats.append(QPair<QString, QString>{"Gesamt", ""});

We must help the C++17 compiler by spelling out the type of the appended element.

QML Runtime Errors

Unfortunately, we don’t have a friendly compiler telling us which lines of our QML code are deprecated. The documentation page Obsolete QML Types lists the known obsolete types, properties and methods. It’s worth going through these lists and checking our QML code for problems. I didn’t find any problems in the harvester QML code.

Before we test the most common usage scenarios (hopefully in an automated way), we update the versions in the import statements. I had to perform the following replacements in the QML files.

Qt 5.12                      ->  Qt 5.15
import QtQuick 2.10          ->  import QtQuick 2.15
import QtQuick.Controls 2.3  ->  import QtQuick.Controls 2.15
import QtMultimedia 5.8      ->  import QtMultimedia 5.15

In my case, testing the most common usage scenarios unearthed a single problem about signal handlers or slots in Connections types.

Warning: QML Connections: Implicitly defined onFoo properties in Connections are deprecated

Problem:

Connections {
    target: csvExportModel
    onMessageOccurred: messagePane.text = message
}

The signal handler onMessageOccurred is implicitly defined as a function.

Fix:

Connections {
    target: csvExportModel
    function onMessageOccurred(message)
    {
        messagePane.text = message
    }
}

We must define onMessageOccurred as a function explicitly with an argument list.

Migrating from Qt 5.15 to Qt 6.2

It’s best to install QtCreator 4.14 or newer, as these versions fully support Qt 6. QtCreator 4.14 adds proper syntax highlighting for Qt 6 code and some improvements for CMake. My development PC ran Ubuntu 18.04.

When I installed Qt 6 with the online installer, I encountered this error:

My Internet search lead me to QTBUG-89218. The comment section reveals that Ubuntu 18.04 is not a supported development platform any more. We have two options. We can upgrade to Ubuntu 20.04 or newer or we can build Qt 6.2 from sources. I decided to upgrade my Ubuntu version.

Building with CMake

Updating CMakeLists.txt Files

The CMakeLists.txt files refer to Qt 5 explicitly in find_package and target_link_libraries commands.

find_package(Qt5 COMPONENTS Core Gui Qml REQUIRED)
target_link_libraries(${PROJECT_NAME}
  Ag::Can Ag::Hmi Qt5::Core Qt5::Gui Qt5::Qml
)

We must change Qt 5 to Qt 6.

find_package(Qt6 COMPONENTS Core Gui Qml REQUIRED)
target_link_libraries(${PROJECT_NAME}
  Ag::Can Ag::Hmi Qt6::Core Qt6::Gui Qt6::Qml
)

Qt5 was built on C++11. The top-level CMakeLists.txt file contained the following lines.

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

Qt6 requires C++17. We must change the top-level CMakeLists.txt file accordingly.

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

Setting Up the QtCreator Kit

When I started QtCreator the first time after installing Qt 6, the auto-detected kit for Qt 6 was messed up. It referred to outdated C and C++ compilers from a Qt 5.14 installation and the system CMake 3.16 from Ubuntu 20.04. We can fix this mess in the QtCreator dialog Tools | Options | Kits.

  • We clone the auto-detected read-only kit for Qt 6.2.
  • We define /usr/bin/gcc and /usr/bin/g++ from Ubuntu 20.04 as the new C and C++ Compilers. Both compilers are version 9.3. GCC9 supports C++17. If we must work with different compiler versions, we set the Compilers to /usr/bin/gcc-9 and /usr/bin/g++-9.
  • We define the CMake coming with Qt6 – /path/to/Qt-6.2.0/Tools/CMake/bin/cmake (version 3.21) – as the CMake Tool of the kit. Qt 6 requires at least CMake 3.18.
  • The CMake generator is Ninja and the extra generator is <none>.

When we run CMake to configure the project, the CMake command should look similar to this:

/path/to/Qt6.2.0/Tools/CMake/bin/cmake 
    -S /private/Projects/Ag/terminal
    -B /tmp/QtCreator-UDwQep/qtc-cmake-sOofIBPC 
    -GNinja 
    -DCMAKE_BUILD_TYPE:String=Debug
    -DQT_QMAKE_EXECUTABLE:STRING=/path/to/Qt-6.2.0/6.2.0/gcc_64/bin/qmake
    -DCMAKE_PREFIX_PATH:STRING=/path/to/Qt/Qt-6.2.0/6.2.0/gcc_64
    -DCMAKE_C_COMPILER:STRING=/usr/bin/gcc-9
    -DCMAKE_CXX_COMPILER:STRING=/usr/bin/g++-9

We can force a re-configuration of the project by removing the build directory recursively and by running Build | Run CMake, or by pressing the button Re-configure with Initial Parameters on the page Projects | Build & Run | Desktop Qt 6.2.0 GCC 64bit | Build Settings.

Core5Compat Library

The Core5Compat library adds the obsolete Qt 5 classes and functions that didn’t make it into Qt 6. We can add Core5Compat to the find_package commands and Qt6::Core5Compat to the target_link_libraries commands. If we do, the compiler will flag occurrences of QRegExp, QTextCodec and some other classes from Qt6::Core as warnings instead of errors (see this post for a mapping between obsolete Qt 5 classes and their Qt 6 replacements).

Core5Compat makes the transition from Qt 5 to Qt 6 smoother. We must fix fewer errors before our application builds and runs again. I didn’t use Core5Compat, because I learned about it too late. I could fix the resulting errors in a mechanical way like replacing QRegExp functions by their counterparts in QRegularExpression.

C++ Compiler Errors and Warnings

Modules Missing in Qt 6.0 and 6.1 Now Available in Qt 6.2

Qt 5 modules like Multimedia, SerialBus, SerialPort, RemoteObjects, Virtual Keyboard, Charts, Bluetooth, WebEngine and WebView didn’t make it into Qt 6.0 (see this post for a complete list). A few became available in Qt 6.1 (April 2021). Qt 6.2, which was released in September 2021, contains all modules from Qt 5.15 and has long-term support.

As the harvester application depends on SerialBus and Multimedia, Qt 6.2 is the first version fit for product releases. With Qt 6.0 and 6.1, I commented out the parts using Multimedia and performed a very quick and very dirty migration of SerialBus. The harvester application uses QtCanBus from SerialBus.

New Qt Module StateMachine

The state machine framework with classes like QStateMachine, QState and QFinalState was moved from the module Core to the new module StateMachine. We add StateMachine to the find_package call and Qt6::StateMachine to the target_link_libraries call in a CMakeLists.txt file.

Error: no match for ‘operator<’ (operand types are ‘const QVariant’ and ‘const QVariant’)

Problem:

QMap<std::pair<QString, QVariant>, QObject *> m_entities;
m_impl->m_entities.insert(it.key(), it.value());

The function it.key() returns an object of type std::pair<QString, QVariant>, which is the same as the key type of the QMap. QMap requires the definition of operator< on the key type to know where to insert new values.

QMap compares whether the pair p1 is less than p2, where both p1 and p2 have the type std::pair<QString, QVariant>. If p1.first is equal to p2.first, the comparison must evaluate p1.second < p2.second. G++-9 rightly complains that operator< is not defined for QVariants. G++-7 overlooked the missing operator< for QVariants.

Fix:

QMap<std::pair<QString, QString>, QObject *> m_entities;
m_impl->m_entities.insert(it.key(), it.value());

Converting a QVariant into a QString with QVariant::toString() works for most types supported by QVariant. As m_entities only uses supported types for the second element of its key, we can safely replace QVariant by QString in the key type.

Error: QTextCodec: No such file or directory

Problem:

#include <QTextCodec>
...
QTextStream is{&csvFile};
is.setCodec(QTextCodec::codecForName("ISO-8859-1"));

The class QTextCodec was removed from Qt 6 and was replaced by the new class QStringConverter. Similarly, the classes QTextEncoder and QTextDecoder were replaced by QStringEncoder and QStringDecoder (see this post). Code using any of the old classes doesn’t compile.

Fix:

#include <QStringConverter>
...
QTextStream is{&csvFile};
is.setEncoding(QStringConverter::Latin1);

We include the header of the replacement class QStringConverter. A search through the functions of QStringConverter makes setEncoding the most likely replacement for setCodec. Understanding that ISO-8859-1 is the formal name for Latin1 helps us call setEncoding with the right constant QStringConverter::Latin1.

Error: QRegExp: No such file or directory

Problem:

#include <QRegExp>

// In anonymous namespace
QRegExp &rxHexFilename()
{
    static QRegExp rx("_(A\d\d)_V_(\d\d)_(\d\d)\.hex$");
    return rx;
}

// In constructor
auto pos = rxHexFilename().indexIn(fileName);
auto ecuName = rxHexFilename().cap(1);
if (pos == -1 || ...) {
    return;
}
m_version = QString("v%1.%2")
    .arg(rxHexFilename().cap(2).toUInt())
    .arg(rxHexFilename().cap(3).toUInt());
m_ecuType = fileName.left(fileName.size() - 
    rxHexFilename().matchedLength());

Replacing QRegExp – a relic of Qt 4 – by QRegularExpression has been in the making since Qt 5.0. QRegularExpression is the only way to work with regular expressions in Qt 6. The interface has changed considerably.

Fix:

#include <QRegularExpression>

// In anonymous namespace
const QRegularExpression rxHexFilename("_(A\d\d)_V_(\d\d)_(\d\d)\.hex$");

// In constructor
auto match = rxHexFilename.match(fileName);
auto ecuName = match.captured(1);
if (!match.hasMatch() || ...) {
    return;
}
m_version = QString("v%1.%2")
    .arg(match.captured(2).toUInt())
    .arg(match.captured(3).toUInt());
m_ecuType = fileName.left(fileName.size() - 
    match.capturedLength(0));

The function for matching a string against a regular expression has got its natural name: match (instead of indexIn). It returns a QRegularExpressionMatch object match instead of an index. We retrieve the nth captured substring by calling match.captured(nth). match.hasMatch() tells us whether the string matched the regular expression.

QRegExp::matchedLength returns the length of the substring matching the complete regular expression. This substring is the same as the 0th captured substring match.captured(0), which has the length match.capturedLength(0).

Error: ‘class QString’ has no member named ‘midRef’

Problem:

subDev = m_deviceName.midRef(splitPos + 1).toLatin1();

The function QString::midRef is obsolete in Qt 6. The same goes for the function QString::leftRef.

Fix:

subDev = m_deviceName.mid(splitPos + 1).toLatin1();

We replace QString::midRef and QString::leftRef by QString::mid and QString::left, respectively.

Error: cannot convert ‘QString’ to ‘const QFileInfo&’

Problem:

QString extractVersion(const QFileInfo &info) const;

QString fileName(...);
auto version = extractVersion(fileName);

In Qt 5, the function extractVersion implicitly converts the QString filename into a QFileInfo object with the constructor QFileInfo(const QString &). In Qt 6, this constructor is marked explicit, which blocks the implicit conversion.

Fix:

QString extractVersion(const QFileInfo &info) const;

QString fileName(...);
auto version = extractVersion(QFileInfo(fileName));

We get rid of the error by calling the constructor QFileInfo(const QString &) explicitly.

Error: invalid application of ‘sizeof’ to incomplete type ‘IntegerRangeModel’

Problem:

class IntegerRangeModel;

class DateTimeModel : public QObject
{
    Q_OBJECT
    Q_PROPERTY(IntegerRangeModel* days READ days CONSTANT)

The forward declaration of IntegerRangeModel was good enough for the Q_PROPERTY definition in Qt 5, because days is declared as a pointer. Qt 6 added a static assertion. A further error message documents the violation of the static assertion:

static_assert(sizeof(T), "Type argument of Q_PROPERTY or Q_DECLARE_METATYPE(T*) must be fully defined");

Fix:

#include "IntegerRangeModel.h";

class DateTimeModel : public QObject
{
    Q_OBJECT
    Q_PROPERTY(IntegerRangeModel* days READ days CONSTANT)

We eliminate the error message by including the header file for IntegerRangeModel instead of forward declaring IntegerRangeModel.

Warning: ‘Type’ is deprecated: Use QMetaType::Type instead. [-Wdeprecated-declarations]

Problem:

EntityColumn(const QString &name, QVariant::Type type, ...)

The enumeration QVariant::Type lists the types that can be stored in a QVariant. It is roughly a subset of the enumeration QMetaType::Type, which lists the types that are known to Qt’s meta object system. Replacing QVariant::Type by QMetaType::Type suggested itself. QVariant::Type is not contained in Qt 6 any more.

Fix:

EntityColumn(const QString &name, QMetaType::Type type, ...)

In Qt 6, we use QMetaType::Type instead of QVariant::Type. We must also replace obsolete enum constants like QVariant::Invalid, QVariant::UInt and QVariant::Bool by QMetaType::UnknownType, QMetaType::UInt and QMetaType::Bool, respectively.

Error: cannot convert ‘QVariant::Type’ to ‘QMetaType::Type’

Problem:

bool typesAreAffine(QMetaType::Type sqlType, ...) const;

QSqlField tableColumn = ...;
if (!typesAreAffine(tableColumn.type(), ...)) ...

Originally, the first argument of typesAreAffine had the type QVariant::Type, which was replaced by QMetaType::Type by the previous migration step. The function QSqlField::type with the return type QVariant::Type doesn’t exist in Qt 6.

Fix:

bool typesAreAffine(QMetaType::Type sqlType, ...) const;

QSqlField tableColumn = ...;
if (!typesAreAffine(QMetaType::Type(tableColumn.metaType().id()), ...)) ...

We substitute the Qt 6 function QSqlField::metaType() for the now obsolete Qt 5 function QSqlField::type(). QSqlField::metaType() returns a QMetaType object. We retrieve the type ID of the QMetaType object with id(), which returns an int instead of a QMetaType::Type to be open for custom meta types. QMetaType::Type(typeID) creates a enum constant from the integer typeID.

Error: warning: conversion from ‘qsizetype’ {aka ‘long long int’} to ‘int’ may change value [-Wconversion]

Problem:

QList<QFileInfo> m_dirEntries.

int DirectoryModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return m_impl->m_dirEntries.size();
}

Starting with Qt 6.0, QList<T>::size() has the return type qsizetype, which is equivalent to long long int. The class DirectoryModel indirectly derives from QAbstractItemModel, which declares the pure virtual function rowCount like this:

virtual int rowCount(const QModelIndex &parent = QModelIndex()) const = 0

The return statement may narrow a long long int value to an int value, which may change the value. It seems that the Qt developers forgot to change the return type of rowCount from int to qsizetype.

Functions like beginInsertRows, beginRemoveRows, beginMoveRows and beginInsertColumns also take int-type arguments. We may have to watch out for narrowing conversions as well.

Fix:

QList<QFileInfo> m_dirEntries.

int DirectoryModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent)
    return static_cast<int>(m_impl->m_dirEntries.size());
}

Sometimes there is no way around a static cast. This is one of those times. We force the qsizetype value into an int value and silence the error.

Warning: conversion from ‘size_t’ {aka ‘long unsigned int’} to ‘uint’ {aka ‘unsigned int’} may change value [-Wconversion]

Problem:

enum class UnitId : quint16 { ... }

inline uint qHash(UnitId unit)
{
    return qHash(static_cast<quint16>(unit));
}

qHash functions return uint values in Qt 5, where uint is unsigned int. In Qt 6, they return size_t values, where size_t is long unsigned int. The qHash function in the return statement is a built-in hash function. It returns a long unsigned int value, which may be narrowed to a an unsigned int value by the custom-defined hash function. As this may change the value, the compiler emits a warning.

Fix:

enum class UnitId : quint16 { ... }

inline size_t qHash(UnitId unit)
{
    return qHash(static_cast<quint16>(unit));
}

We change the return type of the custom-defined hash function from uint to size_t.

Warning: ‘static QQmlFileSelector* QQmlFileSelector::get(QQmlEngine*)’ is deprecated [-Wdeprecated-declarations]

Problem:

auto fs = QQmlFileSelector::get(engine);
fs->setExtraSelectors({"left"});

The static function QQmlFileSelector::get returns the file selector currently active on the QML engine. It is obsolete in Qt 6, because it duplicates the functionality provided by the QQmlFileSelector constructor.

Fix:

auto fs = new QQmlFileSelector(engine);
fs->setExtraSelectors({"left"});

Creating a QQmlFileSelector object on the heap does the same as calling QQmlFileSelector::get. We must create the object on the heap, because the constructor argument engine takes ownership of the file selector.

Error: using typedef-name ‘using QStringList = class QList<QString>’ after ‘class’

Problem:

class QStringList;

An included Qt header file introduces the type definition using QStringList = class QList<QString>. The problematic line forward declares this type definition, which the compiler doesn’t like.

Fix:

#include <QStringList>

We replace the forward declaration by the inclusion of the header file.

Error: ‘QLatin1Literal’ was not declared in this scope; did you mean ‘QStringLiteral’?

Problem:

QStringList errors;
Q_ASSERT_X(false, __PRETTY_FUNCTION__, 
    errors.join(QLatin1Literal("; ")).toUtf8());

QLatin1Literal doesn’t exist in Qt 6 any more.

Fix:

QStringList errors;
Q_ASSERT_X(false, __PRETTY_FUNCTION__, 
    errors.join(QLatin1String("; ")).toUtf8());

We replace QLatin1Literal by QLatin1String.

Error: No type name ‘State’ in QMediaPlayer

Problem:

void onStateChanged(QMediaPlayer::State state);

connect(&m_impl->m_player, &QMediaPlayer::stateChanged,
        m_impl, &Impl::onStateChanged);

if (m_player.state() != QMediaPlayer::PlayingState) { ... }

We replace QMediaPlayer::State by QMediaPlayer::PlaybackState and connect the slot onStateChanged with the signal QMediaPlayer::playbackStateChanged. We also need to replace calls to QMediaPlayer::state() by QMediaPlayer::playbackState().

Fix:

void onStateChanged(QMediaPlayer::PlaybackState state);

connect(&m_impl->m_player, &QMediaPlayer::playbackStateChanged,
        m_impl, &Impl::onStateChanged);

if (m_player.playbackState() != QMediaPlayer::PlayingState) { ... }

Error: ‘QMediaPlaylist’: No such file or directory

Problem:

#include <QMediaPlaylist>

The page Changes to Qt Multimedia informs us that the class QMediaPlaylist was removed from Qt 6. The application plays different MP3 files when info, warning or error dialogs are shown. It passes a QMediaPlaylist with the correct MP3 file to QMediaPlayer. Users can also change the playback volume.

Fix:

QMediaPlaylist is replaced by QMediaPlayer::setSource. The volume cannot be changed directly with QMediaPlayer::setVolume but is changed indirectly with QAudioOutput::setVolume. The following error messages about QMediaPlayer and QMediaPlaylist tell us what to fix.

Error: No member named ‘setVolume’ in ‘QMediaPlayer’

Problem:

m_player.setVolume(80);

Qt 6 moved the functions setVolume and volume from QMediaPlayer to QAudioOutput.

Fix:

The client class using QMediaPlayer must register a QAudioOutput object with the QMediaPlayer object m_player in its constructor. We must tell the QAudioOutput object on which loudspeaker it shall play the MP3 file. We can access the default loudspeaker with QMediaDevices::defaultAudioOutput. That’s good enough for the terminal hardware, which has only one loudspeaker.

The client class sets the volume to a default value (e.g., 0.8). Note that the new QAudioOutput::setVolume takes a floating-point value between 0.0 and 1.0 as an argument, whereas the old QMediaPlayer::setVolume took an integer between 0 and 100.

auto audioOut = new QAudioOutput{};
audioOut->setDevice(QMediaDevices::defaultAudioOutput());
audioOut->setVolume(0.8f);
m_player.setAudioOutput(audioOut);

The setVolume(int vol) function of the client class changes the volume like this:

m_player.audioOutput()->setVolume(0.8f);

Error: QMediaPlayer cannot play back a QMediaPlaylist any more

Problem:

Of course, the title error message is not a real compiler error. As QMediaPlaylist was removed from Qt 6, the following playback function of an error category does not compile any more.

void AudioService::Impl::playFeedback(int category)
{
    m_playlist.addMedia(m_audioFiles[category]);
    m_player.play();
}

m_audioFiles[category] returns the QRC URL of the MP3 file for the given error category. For example, it returns QUrl("qrc:/Can/Audio/ding.mp3") for the category 2.

Fix:

The modified function for playing an MP3 file for the given category looks as follows.

void AudioService::Impl::playFeedback(int category)
{
    m_player.setSource(m_audioFiles[category]);
    m_player.play();
}

QML Warnings, Errors and Improvements

Remove versions from import statements

Problem:

import QtQuick 2.15
import QtQuick.Controls 2.15
import Ag.Models 1.0

Qt 5 requires a version for the imported modules. Qt 6 doesn’t complain about these versions, but it doesn’t require them any more.

Fix:

import QtQuick
import QtQuick.Controls
import Ag.Models

Just importing a module without a version is enough in Qt 6. We remove the versions from all the import statements.

Warning: Parameter “page” is not declared. Injection of parameters into signal handlers is deprecated.

Problem:

// File: RDirectBar.qml
Pane 
{
    signal selectedPage(url page, bool fullscreen)

// File: main.qml
RDirectBar
{
    onSelectedPage: { ... }

The signal selectedPage is connected to the signal handler onSelectedPage in the instantiation of RDirectBar. Qt 6 accepts the old-style signal handlers with a warning.

Fix:

The new way is to use arrow functions or anonymous functions (see Signal Parameters in the Qt 6.2 documentation). We would call them lambda functions in C++.

// File: RDirectBar.qml
Pane 
{
    signal selectedPage(url page, bool fullscreen)

// File: main.qml
RDirectBar
{
    // Arrow function
    onSelectedPage: (page, fullscreen) => { ... }

    // Anonymous function (alternative)
    onSelectedPage: function (page, fullscreen) { ... }

Signal handlers without parameters need not be changed from Qt 5 to Qt 6.

Понравилась статья? Поделить с друзьями:
  • Error end of centdir 64 signature not where expected prepended bytes
  • Error encountered while reading jpeg image
  • Error encountered while performing the operation look at the information window for more details
  • Error encountered while invoking java web start sys exec как решить
  • Error encountered while importing a file zbrush