我正在移植"移植"我的CLI应用程序使用Qt的GUI。
我基本上在GUI中设置了程序的每个选项,然后按下一个运行程序主要功能的按钮。
在CLI版本中,我有一些std::cout
报告控制台的进度。
我也需要在GUI中向用户报告进度,但我不确定最好的方法是什么。
我尝试了一种简单的方法,即使用this将cout重定向到QTextEdit,但它只在最后用all输出进行更新。
我可以用QText替换每个cout
,但是我也想在控制台中使用进度输出在控制台中运行应用程序..,当用参数调用程序时。
所以我的问题是,是否有一种方法,设计模式,工具,允许我调用类似reportProgress("I am here");
的内容,如果从GUI调用,将在QText中显示,如果从控制台调用则在控制台中输出(或参数)?
或者,我是否必须编写报告程序进度的两个版本?
答案 0 :(得分:2)
我用来报告多种类型输出的方法是使用抽象"记录器"基类。然后,从Logger继承类,一个用于GUI,用于CLI或任何您想要登录的其他类。发送到日志的每个对象都只发出一个Log(const QString&),由相关类提取。
/// An interface to be implemented by loggers.
class ILogger : public QObject
{
Q_OBJECT
public:
ILogger(QObject* parent = {});
Q_SLOT virtual void Log(const QString& txt) = 0;
};
ILogger::ILogger(QObject* parent) : QObject(parent) {}
/// Logs to a QPlainTextEdit
class TextBoxGUILogger : public ILogger
{
Q_OBJECT
public:
TextBoxGUILogger(QObject* parent = {});
void setWidget(QPlainTextEdit*);
void Log(const QString& txt) override;
private:
QPointer<QTextEdit> m_txtEditBox;
};
TextBoxGUILogger::TextBoxGUILogger(QObject* parent) : ILogger(parent) {}
void TextBoxGUILogger::setWidget(QPlainTextEdit* edit)
{
m_txtEditBox = edit;
}
void TextBoxGUILogger::Log(const QString& txt)
{
if (m_txtEditBox) m_txtEditBox->append(txt);
}
/// Logs to the standard output.
class CLILogger : public ILogger
{
Q_OBJECT
public:
CLILogger(QObject* parent = {});
void Log(const QString& txt) override;
};
CLILogger::CLILogger(QObject* parent) : ILogger(parent) {}
void CLILogger::Log(const QString& txt)
{
printf("%s", txt.toLocal8Bit().constData());
}
/// Logs to a file.
class FileLogger : public ILogger
{
Q_OBJECT
public:
FileLogger(QObject* parent = {});
/// The file can be owned by another object, or it can be made a child
/// of the logger. In either case the behavior will be correct.
void setFile(QFile*);
void Log(const QString& txt) override;
private:
QPointer<QFile> m_file;
};
FileLogger::FileLogger(QObject* parent) : ILogger(parent) {}
void FileLogger::setFile(QFile* file)
{
m_file = file;
}
void FileLogger::Log(const QString& txt)
{
if (m_file)
m_file->write(txt.toLocal8Bit().constData());
}
因此,您现在可以创建相关的记录器......
对于标准输出(CLI): -
ILogger* pLogger = new CLILogger;
或QPlainTextEdit
: -
ILogger* pLogger = new TextBoxGuiLogger;
最后,到一个文件: -
ILogger* pLogger = new FileLogger;
要记录的每个类都连接到记录器: -
// Qt 5 connect syntax
connect(someClass, &SomeClass::Log, pLogger, &ILogger::Log);
这允许您同时创建一个或多个日志记录对象,并且记录的对象不关心正在进行日志记录的对象,它们只是发出信号: -
emit Log("Log this text");
答案 1 :(得分:1)
有QProgressBar
可以满足您的需求。这是一个GUI元素,据我所知,CLI没有任何内容。
答案 2 :(得分:0)
据我所知,Qt中没有这样的内置API,但您可以在reportProgress()函数中轻松实现它。创建QApplication
时,您可以在构造函数中定义其类型,具体取决于它是控制台还是GUI应用程序:
QApplication :: QApplication(int&amp; argc,char ** argv,Type type)
其中Type
可以QApplication::Tty
或QApplication::GuiClient
等。
在reportProgress()函数中,您可以使用QApplication::type()
函数查询应用程序的类型,例如:
void reportProgress() {
QApplication::Type t = QApplication::type();
if (t == QApplication::Tty) {
// console output
} else {
// output to text edit, etc.
}
[..]
}
答案 3 :(得分:0)
在Windows中,您可以通过cat
简单地管理GUI程序的输出。那么你必须首先创建或安装cat
,但那是微不足道的。或者,您可以将程序构建为控制台子系统,或使用GUI子系统并让程序创建控制台。
没有真正需要做更多花哨的事情,但如果这感觉很可取,那么在Windows中解除事物的一种简单而好的方法就是通过Windows邮件地址将进度事件发布到GUI。
总结:管道输出最简单,然后创建一个控制台作为下一个最简单的(单个API调用,或构建为控制台子系统),然后最复杂的,添加一个事件驱动的进度GUI。