Cara mencetak ke konsol saat menggunakan Qt

159

Saya menggunakan Qt4 dan C ++ untuk membuat beberapa program dalam grafik komputer. Saya harus dapat mencetak beberapa variabel di konsol saya saat run-time, tidak men-debug, tetapi couttampaknya tidak berfungsi bahkan jika saya menambahkan perpustakaan. Apakah ada cara untuk melakukan ini?

lesolorzanov
sumber
3
Bisakah Anda menguraikan cout tidak bekerja karena itu pasti akan berhasil. Apakah Anda mendapatkan kesalahan kompilasi. Bisakah Anda menunjukkan contoh kode cout yang tidak berfungsi untuk Anda? Juga jelaskan bagaimana Anda menjalankan aplikasi. Apakah Anda menjalankannya dari konsol atau dari dalam IDE dan tidak melihat output ke jendela outputnya?
Arnold Spence
Hanya untuk kelengkapan: @ArnoldSpence - tanpa perpustakaan, saya mengerti error: ‘cout’ was not declared in this scope; dengan iostream, saya dapat error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ...; menggunakan perintah dalam jawaban malah berfungsi dengan baik.
sdaau
Sulit untuk menawarkan solusi ketika pernyataan masalahnya sederhana, "itu tidak berhasil". Harap edit pertanyaan Anda untuk memberikan deskripsi yang lebih lengkap tentang apa yang Anda harapkan terjadi dan bagaimana hal itu berbeda dari hasil yang sebenarnya. Lihat Cara Meminta petunjuk tentang apa yang membuat penjelasan yang baik.
Toby Speight
Dalam hal ini, Anda harus secara eksplisit menentukan bahwa "variabel" tersebut adalah objek Qt-spesifik (seperti QString).
user202729

Jawaban:

203

Jika cukup baik untuk dicetak stderr, Anda dapat menggunakan stream berikut yang awalnya dimaksudkan untuk debugging:

#include<QDebug>

//qInfo is qt5.5+ only.
qInfo() << "C++ Style Info Message";
qInfo( "C Style Info Message" );

qDebug() << "C++ Style Debug Message";
qDebug( "C Style Debug Message" );

qWarning() << "C++ Style Warning Message";
qWarning( "C Style Warning Message" );

qCritical() << "C++ Style Critical Error Message";
qCritical( "C Style Critical Error Message" );

// qFatal does not have a C++ style method.
qFatal( "C Style Fatal Error Message" );

Meskipun seperti yang ditunjukkan dalam komentar, ingatlah bahwa pesan qDebug dihapus jika QT_NO_DEBUG_OUTPUTdidefinisikan

Jika Anda perlu stdout, Anda dapat mencoba sesuatu seperti ini (seperti yang ditunjukkan Kyle Strand):

QTextStream& qStdOut()
{
    static QTextStream ts( stdout );
    return ts;
}

Anda dapat menelepon sebagai berikut:

qStdOut() << "std out!";
Goz
sumber
1
Saya bertanya, ketika tidak melakukan debugging, harus ada fungsi yang memungkinkan saya untuk menulis pesan di konsol selama runtime, bukan selama debugging.
lesolorzanov
11
Terlepas dari namanya, fungsi itu tidak terkait dengan debugging dengan debugger. Ini adalah fungsi praktis yang disediakan Qt untuk mengirim output ke stderr yang dapat dihapus dari kompilasi dengan sebuah define. Jadi ini adalah alternatif untuk mencapai output ke konsol saat runtime.
Arnold Spence
Terima kasih banyak, saya menggunakan ini :). Saya kira tidak perlu bagi saya untuk menulis kode apa pun yang saya gunakan. Terima kasih! Ini sangat berguna.
lesolorzanov
51
#include <QDebug>
ducky
62
Tolong jangan gunakan qDebug untuk semua output konsol. Hanya gunakan untuk cetakan debug yang benar, gunakan qWarning, qCritical dan qFatal untuk kesalahan dan peringatan. Karena pernyataan qDebug dapat dihapus saat kompilasi dengan QT_NO_DEBUG_OUTPUT untuk menghemat kinerja dan menghentikan aplikasi dari mengacaukan output.
JustMaximumPower
150

Saya menemukan ini yang paling berguna:

#include <QTextStream>

QTextStream out(stdout);
foreach(QString x, strings)
    out << x << endl;
CapelliC
sumber
14
Saya tidak tahu mengapa jawaban tidak diterima, tetapi yang paling bermanfaat pasti.
Semyon Danilov
4
Sepakat. stderr adalah untuk, yah, kesalahan (dan debugging). Ini harus menjadi jawaban yang diterima karena itu satu-satunya yang menggunakan stdout DAN qt.
Marshall Eubanks
1
Yang ini bekerja untuk saya - dan sepertinya cara yang benar untuk menampilkan info melalui cout
Michael Vincent
2
Jika Anda memasukkan informasi dari jawaban Goz tentang cara mencetak kesalahan / peringatan, bersama dengan sedikit informasi (sayangnya kurang dari jawaban Goz tetapi hadir di komentar di bawahnya) tentang apa yang qDebug()sebenarnya dilakukan dll, ini akan menjadi jawaban yang unggul (IMO sudah unggul karena OP meminta sesuatu untuk diganti std::cout, tetapi 40ish pemilih tampaknya tidak setuju).
Kyle Strand
QTextStream qStdout() { return {stdout}; }mungkin cara yang berguna untuk membungkus ini, konsisten dengan qWarning()dll. Dan mungkin beberapa staticnegara untuk menghindari streaming sementara?
Yakk - Adam Nevraumont
36

Menulis untuk stdout

Jika Anda menginginkan sesuatu yang, seperti std::cout, menulis ke output standar aplikasi Anda, Anda dapat melakukan hal berikut ( kredit ke CapelliC ):

QTextStream(stdout) << "string to print" << endl;

Jika Anda ingin menghindari membuat QTextStreamobjek sementara , ikuti saran Yakk di komentar di bawah ini untuk membuat fungsi untuk mengembalikan staticpegangan untuk stdout:

inline QTextStream& qStdout()
{
    static QTextStream r{stdout};
    return r;
}

...

foreach(QString x, strings)
    qStdout() << x << endl;

Ingat untuk flushstreaming secara berkala untuk memastikan output benar-benar dicetak.

Menulis untuk stderr

Perhatikan bahwa teknik di atas juga dapat digunakan untuk output lain. Namun, ada lebih banyak cara yang dapat dibaca untuk menulis stderr( kredit ke Goz dan komentar di bawah jawabannya):

qDebug() << "Debug Message";    // CAN BE REMOVED AT COMPILE TIME!
qWarning() << "Warning Message";
qCritical() << "Critical Error Message";
qFatal("Fatal Error Message");  // WILL KILL THE PROGRAM!

qDebug()ditutup jika QT_NO_DEBUG_OUTPUTdihidupkan pada waktu kompilasi.

(Goz mencatat dalam komentar bahwa untuk aplikasi non-konsol, ini dapat dicetak ke aliran yang berbeda dari stderr.)


CATATAN: Semua metode cetak Qt mengasumsikan bahwa const char*argumen adalah string bersandi ISO-8859-1 dengan \0karakter terminating .

Kyle Strand
sumber
1
QTextStream qStdout() { static QTextStream r{stdout}; return r; }?
Yakk - Adam Nevraumont
1
@ Yakk Saran yang bagus! Saya akan memasukkan jawaban saya.
Kyle Strand
qFatal () mendapat kesalahan saat kompilasi dengan QT5. a membaca posting, bahwa itu bukan untuk (berada di sana / bekerja) toh ... jangan gunakan itu! :)
relascope
1
@KyleStrand Tidak bisakah Anda menggunakan fungsi untuk itu? template <typename C> constexpr typename std::remove_const<typename std::remove_reference<C>::type>::type& no_const(C* c) { return const_cast<typename std::remove_const<typename std::remove_reference<C>::type>::type&>(*c); } Gunakan: no_const(this).method() . Anda bisa menyuntikkan fungsi itu sebagai metode ke dalam kelas, dan kemudian Anda bahkan tidak perlu lulus this: Foo& no_const() const { return ::no_const(this); } Tidak ada kesalahan ketik, saya janji.
Pasang kembali Monica
1
@Mitch Hm, meninjau tautan itu dan dokumentasi Qt, Anda benar; Saya tidak melihat apa pun untuk menunjukkan bahwa ada masalah nyata yang diketahui disebabkan oleh QTextStreamobjek sementara . Diedit.
Kyle Strand
32

Tambahkan ini ke file proyek Anda:

CONFIG += console
Kyle Lutz
sumber
5
Tidak ada informasi yang diberikan dalam pertanyaan tentang sistem pembangunan mana yang sedang digunakan. Ini hanya relevan saat menggunakan qmake.
Kyle Strand
19

Variabel apa yang ingin Anda cetak? Jika maksud Anda QStrings, itu perlu dikonversi ke c-Strings. Mencoba:

std::cout << myString.toAscii().data();
Sebastian Negraszus
sumber
8
@CoderaPurpa Anda perlu menambahkan#include <iostream>
Sebastian Negraszus
myString.toUtf8().data()lebih baik karena mencetak Karakter di luar rentang ascii. Karakter Cina misalnya
peterchaula
8

Ia juga memiliki sintaksis yang mirip dengan prinft, misalnya:

qDebug ("message %d, says: %s",num,str); 

Sangat berguna juga

ulitosCoder
sumber
8

Buka Proyek Properties -> Linker-> System -> SubSystem, lalu setel ke Console(/S).

Son Vu
sumber
1
Ini (seperti jawaban Kyle Lutz) khusus untuk sistem pembangunan.
Kyle Strand
3

Bagaimana dengan menyertakan pustaka iostream dan tepatnya cout adalah objek std seperti ini:

#include <iostream>

std::cout << "Hello" << std::endl;
Emerald Cottet
sumber
1

Jika Anda mencetak ke stderr menggunakan perpustakaan stdio, panggilan ke fflush(stderr)harus menyiram buffer dan membuat Anda masuk secara real-time.

Andrew Prock
sumber
1
#include <QTextStream>
...
qDebug()<<"Bla bla bla";
Amir Touitou
sumber
0

Nah, setelah mempelajari beberapa contoh di Internet yang menggambarkan cara membuat pesan dari GUI di Qt ke stdout, saya telah memperbaiki contoh yang berdiri sendiri tentang pengalihan pesan ke konsol, melalui qDebug () dan menginstal qInstallMessageHandler (). Konsol akan ditampilkan bersamaan dengan GUI dan dapat disembunyikan jika dianggap perlu. Kode mudah diintegrasikan dengan kode yang ada di proyek Anda. Berikut ini adalah contoh lengkap dan jangan ragu untuk menggunakannya dengan cara apa pun yang Anda suka, selama Anda mematuhi Lisensi GNU GPL v2. Anda harus menggunakan semacam bentuk dan MainWindow saya pikir - jika sampel akan berjalan, tetapi mungkin macet ketika dipaksa untuk berhenti. Catatan: tidak ada cara untuk keluar melalui tombol tutup atau menu tutup karena saya telah menguji alternatif itu dan aplikasi akan macet akhirnya setiap sekarang dan kemudian. Tanpa tombol tutup aplikasi akan stabil dan Anda dapat menutupnya dari jendela utama. Nikmati!

#include "mainwindow.h"
#include <QApplication>

//GNU GPL V2, 2015-02-07
#include <QMessageBox>
#include <windows.h>
#define CONSOLE_COLUMNS 80
#define CONSOLE_ROWS    5000
#define YOURCONSOLETITLE "Your_Console_Title"

typedef struct{

    CONSOLE_SCREEN_BUFFER_INFOEX conScreenBuffInfoEX;

    HANDLE con_screenbuf;
    HWND hwndConsole;
    HMENU consoleMenu ;
    QString consoleTitle;

    QMessageBox mBox;
    QString localMsg;
    QString errorMessage;
    WINBOOL errorCode;

} consoleT;

static consoleT *console;

BOOL WINAPI catchCTRL( DWORD ctrlMsg ){

        if( ctrlMsg == CTRL_C_EVENT ){

            HWND hwndWin = GetConsoleWindow();
               ShowWindow(hwndWin,SW_FORCEMINIMIZE);
        }

    return TRUE;
}

void removeCloseMenu(){

    int i;

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

        console->hwndConsole = FindWindowW( NULL, console->consoleTitle.toStdWString().data());

        if(console->hwndConsole != NULL)
            break;
    }

    if( !(console->errorCode = 0) && (console->hwndConsole == NULL))
            console->errorMessage += QString("\nFindWindowW error: %1 \n").arg(console->errorCode);

    if( !(console->errorCode = 0) &&  !(console->consoleMenu = GetSystemMenu( console->hwndConsole, FALSE )) )
        console->errorMessage += QString("GetSystemMenu error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = DeleteMenu( console->consoleMenu, SC_CLOSE, MF_BYCOMMAND )))
           console->errorMessage += QString("DeleteMenu error: %1 \n").arg(console->errorCode);
}

void initialiseConsole(){

    console->conScreenBuffInfoEX.cbSize = sizeof(CONSOLE_SCREEN_BUFFER_INFOEX);
    console->consoleMenu = NULL;
    console->consoleTitle = YOURCONSOLETITLE;
    console->con_screenbuf = INVALID_HANDLE_VALUE;
    console->errorCode = 0;
    console->errorMessage = "";
    console->hwndConsole = NULL;
    console->localMsg = "";

    if(!(console->errorCode = FreeConsole()))
        console->errorMessage += QString("\nFreeConsole error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = AllocConsole()))
        console->errorMessage += QString("\nAllocConsole error: %1 \n").arg(console->errorCode);

    if( (console->errorCode = -1) && (INVALID_HANDLE_VALUE ==(console->con_screenbuf = CreateConsoleScreenBuffer( GENERIC_WRITE | GENERIC_READ,0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL))))
        console->errorMessage += QString("\nCreateConsoleScreenBuffer error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = SetConsoleActiveScreenBuffer(console->con_screenbuf)))
        console->errorMessage += QString("\nSetConsoleActiveScreenBuffer error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = GetConsoleScreenBufferInfoEx(console->con_screenbuf, &console->conScreenBuffInfoEX)))
        console->errorMessage += QString("\nGetConsoleScreenBufferInfoEx error: %1 \n").arg(console->errorCode);

    console->conScreenBuffInfoEX.dwSize.X = CONSOLE_COLUMNS;
    console->conScreenBuffInfoEX.dwSize.Y = CONSOLE_ROWS;

    if(!(console->errorCode = SetConsoleScreenBufferInfoEx(console->con_screenbuf, &console->conScreenBuffInfoEX)))
       console->errorMessage += QString("\nSetConsoleScreenBufferInfoEx error: %1 \n").arg(console->errorCode);

    if(!(console->errorCode = SetConsoleTitleW(console->consoleTitle.toStdWString().data())))
        console->errorMessage += QString("SetConsoleTitle error: %1 \n").arg(console->errorCode);

    SetConsoleCtrlHandler(NULL, FALSE);
    SetConsoleCtrlHandler(catchCTRL, TRUE);

    removeCloseMenu();

    if(console->errorMessage.length() > 0){
        console->mBox.setText(console->errorMessage);
        console->mBox.show();
    }

}

void messageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg){


    if((console->con_screenbuf != INVALID_HANDLE_VALUE)){

        switch (type) {

        case QtDebugMsg:
            console->localMsg = console->errorMessage + "Debug: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length(), NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            break;

        case QtWarningMsg:
            console->localMsg = console->errorMessage + "Warning: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length() , NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            break;

        case QtCriticalMsg:
            console->localMsg = console->errorMessage + "Critical: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length(), NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            break;

        case QtFatalMsg:
            console->localMsg = console->errorMessage + "Fatal: " + msg;
            WriteConsoleW(console->con_screenbuf, console->localMsg.toStdWString().data(), console->localMsg.toStdWString().length(), NULL, NULL );
            WriteConsoleA(console->con_screenbuf, "\n--\n", 4, NULL, NULL );
            abort();
        }
    }
}



int main(int argc, char *argv[])
{

    qInstallMessageHandler(messageHandler);

    QApplication a(argc, argv);

    console = new consoleT();
    initialiseConsole();

    qDebug() << "Hello World!";

    MainWindow w;
    w.show();

    return a.exec();
}
pengguna2178077
sumber
0

"build & run"> Default untuk "Run in terminal" -> Enable

untuk membersihkan buffer, gunakan perintah ini -> fflush (stdout); Anda juga dapat menggunakan "\ n" di printfatau cout.

r.shams
sumber