Cách in ra bàn điều khiển khi sử dụng Qt


159

Tôi đang sử dụng Qt4 và C ++ để tạo một số chương trình trong đồ họa máy tính. Tôi cần có thể in một số biến trong bảng điều khiển của mình trong thời gian chạy, không gỡ lỗi, nhưng coutdường như không hoạt động ngay cả khi tôi thêm các thư viện. Có cách nào để làm việc này không?


3
Bạn có thể giải thích về cout không hoạt động vì điều đó chắc chắn sẽ làm việc. Bạn có nhận được một lỗi biên dịch. Bạn có thể hiển thị một ví dụ mã của cout không hoạt động cho bạn? Cũng giải thích cách bạn đang chạy ứng dụng. Bạn đang chạy nó từ bàn điều khiển hoặc từ trong IDE và không thấy đầu ra cho cửa sổ đầu ra của nó?
Arnold Spence

Chỉ để hoàn thiện: @ArnoldSpence - không có thư viện, tôi nhận được error: ‘cout’ was not declared in this scope; với iostream, tôi nhận được error: no match for ‘operator<<’ in ‘std::operator<< [with _Traits = std::char_traits<char>](((std::basic_ostream<char>&)(& std::cout)), ...; sử dụng các lệnh trong câu trả lời thay vì hoạt động tốt.
sdaau

Thật khó để đưa ra giải pháp khi tuyên bố vấn đề chỉ đơn giản là "nó không hoạt động". Vui lòng chỉnh sửa câu hỏi của bạn để đưa ra một mô tả đầy đủ hơn về những gì bạn dự kiến ​​sẽ xảy ra và làm thế nào khác với kết quả thực tế. Xem Làm thế nào để hỏi gợi ý về những gì làm cho một lời giải thích tốt.
Toby Speight

Trong trường hợp này, bạn nên xác định rõ ràng rằng các "biến" đó là các đối tượng cụ thể của Qt (chẳng hạn như QString).
dùng202729

Câu trả lời:


203

Nếu nó đủ tốt để in stderr, bạn có thể sử dụng các luồng sau đây dự định để gỡ lỗi:

#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" );

Mặc dù như đã chỉ ra trong các bình luận, hãy nhớ rằng các thông điệp qDebug sẽ bị xóa nếu QT_NO_DEBUG_OUTPUTđược xác định

Nếu bạn cần thiết bị xuất chuẩn, bạn có thể thử một cái gì đó như thế này (như Kyle Strand đã chỉ ra):

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

Sau đó bạn có thể gọi như sau:

qStdOut() << "std out!";

1
Tôi hỏi, trong khi không gỡ lỗi, phải có một chức năng cho phép tôi viết tin nhắn trong bàn điều khiển trong thời gian chạy, không phải trong quá trình gỡ lỗi.
lesolorzanov

11
Mặc dù tên của nó, chức năng đó không liên quan đến gỡ lỗi với trình gỡ lỗi. Đây là một chức năng tiện lợi mà Qt cung cấp để gửi đầu ra tới thiết bị lỗi chuẩn có thể được loại bỏ khỏi quá trình biên dịch với một định nghĩa. Vì vậy, nó là một thay thế để đạt được đầu ra cho giao diện điều khiển trong thời gian chạy.
Arnold Spence

Cảm ơn tất cả các bạn, tôi đang sử dụng cái này :). Tôi đoán không cần thiết sau đó để tôi viết bất kỳ mã nào tôi đã sử dụng. Cảm ơn! Điều này đã được siêu hữu ích.
lesolorzanov

51
#include <QĐebug>
ducky

62
Vui lòng không sử dụng qDebug cho tất cả đầu ra của bàn điều khiển. Chỉ sử dụng nó cho các bản in gỡ lỗi thực sự sử dụng qWarning, qCritical và qFirth cho các lỗi và cảnh báo. Bởi vì các câu lệnh qDebug có thể bị xóa khi biên dịch với QT_NO_DEBUG_OUTPUT để lưu hiệu suất và ngăn ứng dụng làm lộn xộn đầu ra.
JustMaximumPower

150

Tôi thấy điều này hữu ích nhất:

#include <QTextStream>

QTextStream out(stdout);
foreach(QString x, strings)
    out << x << endl;

14
Tôi không biết tại sao câu trả lời không được chấp nhận, nhưng chắc chắn nó hữu ích nhất.
Semyon Danilov

4
Đã đồng ý. stderr là cho, tốt, lỗi (và gỡ lỗi). Đây phải là câu trả lời được chấp nhận vì đây là câu trả lời duy nhất sử dụng thiết bị xuất chuẩn VÀ qt.
Marshall Eubanks

1
Cách này hiệu quả với tôi - và dường như là cách chính xác để xuất thông tin qua cout
Michael Vincent

2
Nếu bạn kết hợp thông tin từ câu trả lời của Goz về cách in lỗi / cảnh báo, cùng với một chút thông tin (đáng buồn là thiếu câu trả lời của Goz nhưng trình bày trong các bình luận bên dưới) về những gì qDebug()vv thực sự làm, thì đây sẽ là câu trả lời vượt trội (IMO nó đã vượt trội hơn vì OP đang yêu cầu thay thế std::cout, nhưng 40 cử tri dường như không đồng ý).
Kyle Strand

QTextStream qStdout() { return {stdout}; }có thể là một cách hữu ích để bọc cái này, phù hợp với qWarning()vv Và có thể một số statictrạng thái để tránh bị gián đoạn tạm thời?
Yakk - Adam Nevraumont 10/03/2015

36

Viêt thư cho stdout

Nếu bạn muốn một cái gì đó, như std::cout, ghi vào đầu ra tiêu chuẩn của ứng dụng của bạn, bạn chỉ cần thực hiện các thao tác sau (ghi có vào CapelliC ):

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

Nếu bạn muốn tránh tạo một QTextStreamđối tượng tạm thời , hãy làm theo đề xuất của Yakk trong các bình luận bên dưới về việc tạo một hàm để trả về một staticđiều khiển cho stdout:

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

...

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

Ghi vào flushdòng theo định kỳ để đảm bảo đầu ra là thực sự in.

Viêt thư cho stderr

Lưu ý rằng kỹ thuật trên cũng có thể được sử dụng cho các đầu ra khác. Tuy nhiên, có nhiều cách dễ đọc hơn để viết stderr(ghi có vào Goz và các bình luận bên dưới câu trả lời của anh ấy):

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()bị đóng nếu QT_NO_DEBUG_OUTPUTđược bật vào thời gian biên dịch.

(Goz lưu ý trong một nhận xét rằng đối với các ứng dụng không có giao diện điều khiển, chúng có thể in ra một luồng khác so với stderr.)


GHI CHÚ: Tất cả các phương pháp in Qt đều cho rằng các const char*đối số là các chuỗi được mã hóa ISO-8859-1 với các \0ký tự kết thúc .


1
QTextStream qStdout() { static QTextStream r{stdout}; return r; }?
Yakk - Adam Nevraumont 10/03/2015

1
@Yakk Gợi ý tốt! Tôi sẽ kết hợp vào câu trả lời của tôi.
Kyle Strand

qFirth () gặp lỗi khi biên dịch với QT5. đọc một bài đăng, dù sao nó cũng không có ý định (ở đó / làm việc) ... đừng sử dụng nó! :)
di cư

1
@KyleStrand Bạn không thể sử dụng một chức năng cho điều đó? 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); } Sử dụng : no_const(this).method() . Bạn có thể đưa chức năng đó như một phương thức vào lớp, và sau đó bạn thậm chí sẽ không cần phải vượt qua this: Foo& no_const() const { return ::no_const(this); } Không lỗi chính tả, tôi hứa.
Phục hồi Monica

1
@Mitch Hừm, xem xét các liên kết đó và tài liệu Qt, bạn đã đúng; Tôi không thấy bất cứ điều gì để chỉ ra rằng có bất kỳ vấn đề thực sự được biết đến gây ra bởi QTextStreamcác đối tượng tạm thời . Đã chỉnh sửa.
Kyle Strand

32

Thêm phần này vào tệp dự án của bạn:

CONFIG += console

5
Không có thông tin nào được đưa ra trong câu hỏi liên quan đến hệ thống xây dựng nào đang được sử dụng. Điều này chỉ có liên quan khi sử dụng qmake.
Kyle Strand

19

Những biến nào bạn muốn in? Nếu bạn có nghĩa là QStrings, những người cần phải được chuyển đổi thành c-String. Thử:

std::cout << myString.toAscii().data();

8
@CoderaPurpa Bạn cần thêm#include <iostream>
Sebastian Negraszus

myString.toUtf8().data()là tốt hơn bởi vì nó in các ký tự bên ngoài phạm vi ascii. Ví dụ, ký tự tiếng Trung Quốc
peterchaula

8

Nó cũng có một cú pháp tương tự như prinft, ví dụ:

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

Cũng rất tiện dụng


8

Đi đến dự án Properties -> Linker-> System -> SubSystem, sau đó đặt nó vào Console(/S).


1
Điều này (như câu trả lời của Kyle Lutz) là hệ thống xây dựng cụ thể.
Kyle Strand

3

Điều gì về việc bao gồm thư viện iostream và chính xác rằng cout là một đối tượng của std như thế này:

#include <iostream>

std::cout << "Hello" << std::endl;

1

Nếu bạn đang in ra stderr bằng thư viện stdio, một lệnh gọi fflush(stderr)sẽ xóa bộ đệm và giúp bạn ghi nhật ký theo thời gian thực.



0

Chà, sau khi nghiên cứu một số ví dụ trên Internet mô tả cách xuất thông điệp từ GUI trong Qt sang thiết bị xuất chuẩn, tôi đã tinh chỉnh một ví dụ độc lập làm việc về chuyển hướng thư đến bảng điều khiển, thông qua qDebug () và cài đặt qInstallMessageHandler (). Bảng điều khiển sẽ được hiển thị cùng lúc với GUI và có thể bị ẩn nếu thấy cần thiết. Mã này dễ dàng tích hợp với mã hiện có trong dự án của bạn. Dưới đây là mẫu đầy đủ và thoải mái sử dụng nó theo bất kỳ cách nào bạn muốn, miễn là bạn tuân thủ Giấy phép GNU GPL v2. Tôi phải sử dụng một hình thức nào đó và MainWindow tôi nghĩ - nếu không thì mẫu sẽ chạy, nhưng có thể bị sập khi buộc phải thoát. Lưu ý: không có cách nào để thoát qua nút đóng hoặc menu đóng vì tôi đã kiểm tra các lựa chọn thay thế đó và ứng dụng cuối cùng sẽ bị sập. Nếu không có nút đóng, ứng dụng sẽ ổn định và bạn có thể đóng nó xuống từ cửa sổ chính. Thưởng thức!

#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();
}

0

"xây dựng và chạy"> Mặc định cho "Chạy trong thiết bị đầu cuối" -> Bật

để xóa bộ đệm sử dụng lệnh này -> fflush (stdout); bạn cũng có thể sử dụng "\ n" trong printfhoặc cout.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.