Qt GUI app:QObject :: connect()失败时会发出警告吗?

时间:2009-09-28 11:21:39

标签: c++ qt signals-slots

我最近将我的Qt项目从Linux迁移到Vista,现在我盲目地调试信号。

在Linux上,如果QObject :: connect()在调试版本中失败,我会在stderr上收到警告消息。在Windows上,GUI应用程序没有控制台输出,只有OutputDebugString调用。

我已经安装了DebugView,它可以很好地捕获我自己的qDebug()输出,但仍然没有警告失败的信号。

一种可能的解决方案是使用QtCreator的自动完成信号,但我喜欢Eclipse,并且使用两者都是PITA。关于如何在运行时获取信号/插槽信息的任何想法?

编辑:我刚刚实现了connect()返回bool,它解决了眼前的问题,可能是丑陋的。但是,这并不能解决QMetaObject::connectSlotsByName()失败的情况,而且这个情况会自动与小部件一起运行。

7 个答案:

答案 0 :(得分:10)

调用静态函数QErrorMessage :: qtHandler()。

根据文档,这'使用qInstallMsgHandler()安装消息处理程序并创建一个显示qDebug(),qWarning()和qFatal()消息的QErrorMessage。

或者,使用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/

答案 1 :(得分:4)

我喜欢的解决方案是设置

QT_FATAL_WARNINGS=1
调试时在程序环境中

。这会使程序崩溃,给你一个很好的回溯,特别是如果你在调试器中运行代码。如果您不想要崩溃,请参阅上面的答案。

答案 2 :(得分:2)

我的方法是用qInstallMsgHandler重新绑定Qt日志记录引擎,然后自己记录到文件和控制台。

这样,我知道所有错误/警告消息都被记录下来,即使在程序停止执行后我也可以分析它们。

P.S:QtCreator拦截这些消息并在应用程序输出窗格中显示它们。

答案 3 :(得分:1)

如果您使用Visual Studio,则可以向任何QT应用程序添加控制台 转到项目属性,在链接器下 - >设置更改“子系统”以说“控制台”

现在重新编译您的代码,您将在激活应用程序时显示控制台。如果你想摆脱它,只需将子系统再次更改为“Windows”

我不确定这是否与QtCreator有关。

另一种选择是使用像AttachConsole()这样的本机win32调用来手动创建控制台并将其附加到stdout和stderr。有关详细信息,请参阅here

答案 4 :(得分:1)

您可以使用官方Qt IDE:QtCreator。它包含一个输出控制台,您可以在其中看到信号的任何问题。在调试和释放运行中输出信号错误。

答案 5 :(得分:1)

大多数时候我只想要一些关注: 只需在“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);

答案 6 :(得分:0)

你可以很容易地重定向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 );