Приложение Qt GUI: предупреждение, если QObject:: connect() не удалось?
Недавно я перенес свой проект Qt с Linux на Vista, и теперь я отслежу сигналы вслепую.
В Linux, если QObject:: connect() терпит неудачу в сборке отладки, я получаю предупреждение о stderr. В Windows нет консольного вывода для графических приложений, только вызов OutputDebugString.
Я уже установил DebugView, и он отлично поймал мой собственный qDebug(), но все еще не предупреждал о неисправных сигналах.
Одним из возможных решений было бы использовать автозаполнение QtCreator для сигналов, но мне нравится Eclipse, и использование обоих - это PITA. Любые идеи о том, как получить информацию о сигнале/слоте во время выполнения?
Изменить: я только что понял, что connect() возвращает bool, что решает ближайшую проблему, уродливую, как это может быть. Однако это не решает случаи, когда QMetaObject:: connectSlotsByName() терпит неудачу, и этот файл запускается автоматически с помощью виджетов.
Ответы
Ответ 1
Вызвать статическую функцию QErrorMessage:: qtHandler().
В соответствии с документацией это "устанавливает обработчик сообщений с помощью qInstallMsgHandler() и создает QErrorMessage, который отображает сообщения qDebug(), qWarning() и qFatal().
В качестве альтернативы установите обработчик сообщений с помощью qInstallMsgHandler().
Другая альтернатива (описанная в сообщении qt-interest) выглядит примерно так:
#ifdef _DEBUG
#define connect( connectStmt ) Q_ASSERT( connect( connectStmt ) )
#endif
... и для чего это стоит, вот несколько отладочных предложений сигналов и слотов, которые я скомпилировал: http://samdutton.wordpress.com/2008/10/03/debugging-signals-and-slots-in-qt/
Ответ 2
Решение, которое мне нравится, это установить
QT_FATAL_WARNINGS=1
в среде программы при отладке. Это приводит к сбою программы, что дает вам хорошую обратную трассировку, особенно если вы запускаете код в отладчике. Если вы не хотите сбой, см. Ответ выше.
Ответ 3
Мой подход заключается в том, чтобы перестроить механизм ведения журнала Qt с помощью qInstallMsgHandler
и выполнить мой собственный журнал как для файлов, так и для консоли.
Таким образом, я знаю, что все сообщения об ошибке/предупреждении записываются, и я могу анализировать их даже после прекращения выполнения программы.
P.S: QtCreator перехватывает эти сообщения и отображает их в панели вывода приложения.
Ответ 4
Если вы используете Visual Studio, вы можете добавить консоль в любое приложение QT.
Перейдите к свойствам проекта, в Linker- > Settings измените "SubSystem", чтобы сказать "Консоль"
Теперь перекомпилируйте свой код, и консоль появится при активации приложения. Если вы хотите избавиться от него, просто замените SubSystem на "Windows"
Я не уверен, возможно ли это с QtCreator.
Другой вариант - использовать собственные вызовы win32, такие как AttachConsole()
, чтобы вручную создать консоль и прикрепить ее к stdout и stderr. см. здесь для получения более подробной информации об этом.
Ответ 5
Вы можете использовать официальный Qt IDE: QtCreator. Он содержит выходную консоль, где вы увидите какие-либо проблемы с сигналами. Сигнальная ошибка выводится в прогоне отладки AND.
Ответ 6
вы можете легко перенаправить stdout/stderr: создать класс, который происходит из std:: basic_streambuf и перегружает xsputn() и overflow(), а затем использовать, например, std:: cerr.rdbuf(instanceOfYourRedirectClass), чтобы перенаправить все stderr ouptut на функцию обратного вызова, которую вы предоставляете.
Вот упрощенная версия того, что я использую; в зависимости от ваших потребностей вам, возможно, придется добавить дополнительную логику, чтобы играть с обработкой символов конца строки и т.д.
template< class Elem = char, class Tr = std::char_traits<Elem> >
class Redirector : public std::basic_streambuf<Elem, Tr>
{
typedef void (*pfncb) ( const Elem*, std::streamsize );
public:
Redirector( std::ostream& a_Stream, pfncb a_Cb ) :
m_Stream( a_Stream ),
m_pCbFunc( a_Cb ),
{
//redirect stream
m_pBuf = m_Stream.rdbuf( this );
};
~Redirector()
{
//restore stream
m_Stream.rdbuf( m_pBuf );
}
std::streamsize xsputn( const Elem* _Ptr, std::streamsize _Count )
{
m_pCbFunc( _Ptr, _Count );
return _Count;
}
typename Tr::int_type overflow( typename Tr::int_type v )
{
Elem ch = Tr::to_char_type( v );
m_pCbFunc( &ch, 1 );
return Tr::not_eof( v );
}
protected:
std::basic_ostream<Elem, Tr>& m_Stream;
std::streambuf* m_pBuf;
pfncb m_pCbFunc;
};
Использование:
void outcallback( const char *ptr, std::streamsize count )
{
if( *ptr != gc_cEOL ) //ignore eof
OutputDebugString( ptr );
}
Redirector<> redirect( std::cout, mycallback );
Ответ 7
В большинстве случаев мне нужно только некоторое время:
Просто поставьте точку останова на строке "int dummyPutBreakpointHere = 23;"
in main.C:
static QtMessageHandler defaultMessageHandler;
void myRazorsharpMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
{
if ( type > QtDebugMsg ) {
int dummyPutBreakpointHere= 23;
}
defaultMessageHandler(type, context, msg);
}
...
later in main(): defaultMessageHandler= qInstallMessageHandler(0);