readAllStandardOutput());}); 连接(进程,&QProcess::readyReadStandardError,[=](){print(进程->readAllStandardError());}); connect(进程,QOverload::of(&QProcess::finished),[=](int-exitCode,QProcess::ExitStatus-ExitStatus){prepareCommandLine();return;}); 进程->设置程序(“/bin/bash”); 进程->开始(); 进程->写入(cmd.toStdString().c_str()); //进程->写入(“\n\r”); 进程->closeWriteChannel(); },c++,qt,c++11,qt5,C++,Qt,C++11,Qt5" /> readAllStandardOutput());}); 连接(进程,&QProcess::readyReadStandardError,[=](){print(进程->readAllStandardError());}); connect(进程,QOverload::of(&QProcess::finished),[=](int-exitCode,QProcess::ExitStatus-ExitStatus){prepareCommandLine();return;}); 进程->设置程序(“/bin/bash”); 进程->开始(); 进程->写入(cmd.toStdString().c_str()); //进程->写入(“\n\r”); 进程->closeWriteChannel(); },c++,qt,c++11,qt5,C++,Qt,C++11,Qt5" />

实时从QProcess获取响应 我在C++编程中是新手,所以我需要帮助逻辑(代码是很棒的)。我想让QTextEdit作为一个类似终端的小部件工作。 我正试图通过QProcess实现这一点,如: void QPConsole::command(QString cmd){ QProcess* process = new QProcess(); connect(process, &QProcess::readyReadStandardOutput, [=](){ print(process->readAllStandardOutput()); }); connect(process, &QProcess::readyReadStandardError, [=](){ print(process->readAllStandardError()); }); connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),[=](int exitCode, QProcess::ExitStatus exitStatus){ prepareCommandLine(); return; }); process->setProgram("/bin/bash"); process->start(); process->write(cmd.toStdString().c_str()); // process->write("\n\r"); process->closeWriteChannel(); } void QPConsole::command(QString cmd){ QProcess*process=新的QProcess(); 连接(进程,&QProcess::readyReadStandardOutput,[=](){print(进程->readAllStandardOutput());}); 连接(进程,&QProcess::readyReadStandardError,[=](){print(进程->readAllStandardError());}); connect(进程,QOverload::of(&QProcess::finished),[=](int-exitCode,QProcess::ExitStatus-ExitStatus){prepareCommandLine();return;}); 进程->设置程序(“/bin/bash”); 进程->开始(); 进程->写入(cmd.toStdString().c_str()); //进程->写入(“\n\r”); 进程->closeWriteChannel(); }

实时从QProcess获取响应 我在C++编程中是新手,所以我需要帮助逻辑(代码是很棒的)。我想让QTextEdit作为一个类似终端的小部件工作。 我正试图通过QProcess实现这一点,如: void QPConsole::command(QString cmd){ QProcess* process = new QProcess(); connect(process, &QProcess::readyReadStandardOutput, [=](){ print(process->readAllStandardOutput()); }); connect(process, &QProcess::readyReadStandardError, [=](){ print(process->readAllStandardError()); }); connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),[=](int exitCode, QProcess::ExitStatus exitStatus){ prepareCommandLine(); return; }); process->setProgram("/bin/bash"); process->start(); process->write(cmd.toStdString().c_str()); // process->write("\n\r"); process->closeWriteChannel(); } void QPConsole::command(QString cmd){ QProcess*process=新的QProcess(); 连接(进程,&QProcess::readyReadStandardOutput,[=](){print(进程->readAllStandardOutput());}); 连接(进程,&QProcess::readyReadStandardError,[=](){print(进程->readAllStandardError());}); connect(进程,QOverload::of(&QProcess::finished),[=](int-exitCode,QProcess::ExitStatus-ExitStatus){prepareCommandLine();return;}); 进程->设置程序(“/bin/bash”); 进程->开始(); 进程->写入(cmd.toStdString().c_str()); //进程->写入(“\n\r”); 进程->closeWriteChannel(); },c++,qt,c++11,qt5,C++,Qt,C++11,Qt5,接下来的问题是: 若我不关闭写入通道(进程->closeWriteChannel),那个么我就会陷入无限循环。如果我真的关闭了它,那么我就记不起状态(有点像创建新会话),例如,如果我执行“pwd”,我会得到结果,但是如果我执行下一个“cd..”然后执行“pwd”,结果与“pwd”的第一个输出相同 所以,我的问题是,是否有可能通过QProcess实现某种实时输出+记住以前的状态(如在real terminal中),或者我必须以其他方式完成。在Python中,我用管道处理子进程,但不知道C++的等值

接下来的问题是: 若我不关闭写入通道(进程->closeWriteChannel),那个么我就会陷入无限循环。如果我真的关闭了它,那么我就记不起状态(有点像创建新会话),例如,如果我执行“pwd”,我会得到结果,但是如果我执行下一个“cd..”然后执行“pwd”,结果与“pwd”的第一个输出相同

所以,我的问题是,是否有可能通过QProcess实现某种实时输出+记住以前的状态(如在real terminal中),或者我必须以其他方式完成。在Python中,我用管道处理子进程,但不知道C++的等值是什么。
一个代码示例会很好。我有QTextEdit部分(将QString参数发送到函数),我需要与控制台交互的部分

想法很简单:保留一个
QProcess
的实例,然后向其写入命令,后跟
\n

下面是一个完整的示例,使用
QMainWindow
Bash
类,将其放入
main.cpp

#include <QtCore>
#include <QtGui>
#include <QtWidgets>

class Bash : public QObject
{
    Q_OBJECT
public:
    explicit Bash(QObject *parent = nullptr) : QObject(parent)
    {

    }

    ~Bash()
    {
        closePrivate();
    }

signals:
    void readyRead(QString);

public slots:
    bool open(int timeout = -1)
    {
        if (m_bash_process)
            return false;

        m_timeout = timeout;

        return openPrivate();
    }

    void close()
    {
        closePrivate();
    }

    bool write(const QString &cmd)
    {
        return writePrivate(cmd);
    }

    void SIGINT()
    {
        SIGINTPrivate();
    }

private:
    //Functions
    bool openPrivate()
    {
        if (m_bash_process)
            return false;

        m_bash_process = new QProcess();

        m_bash_process->setProgram("/bin/bash");

        //Merge stdout and stderr in stdout channel
        m_bash_process->setProcessChannelMode(QProcess::MergedChannels);

        connect(m_bash_process, &QProcess::readyRead, this, &Bash::readyReadPrivate);
        connect(m_bash_process, QOverload<int>::of(&QProcess::finished), this, &Bash::closePrivate);

        m_bash_process->start();

        bool started = m_bash_process->waitForStarted(m_timeout);

        if (!started)
            m_bash_process->deleteLater();

        return started;
    }

    void closePrivate()
    {
        if (!m_bash_process)
            return;

        m_bash_process->closeWriteChannel();
        m_bash_process->waitForFinished(m_timeout);
        m_bash_process->terminate();
        m_bash_process->deleteLater();
    }

    void readyReadPrivate()
    {
        if (!m_bash_process)
            return;

        while (m_bash_process->bytesAvailable() > 0)
        {
            QString str = QLatin1String(m_bash_process->readAll());
            emit readyRead(str);
        }
    }

    bool writePrivate(const QString &cmd)
    {
        if (!m_bash_process)
            return false;

        if (runningPrivate())
            return false;

        m_bash_process->write(cmd.toLatin1());
        m_bash_process->write("\n");

        return m_bash_process->waitForBytesWritten(m_timeout);
    }

    void SIGINTPrivate()
    {
        if (!m_bash_process)
            return;

        QProcess::startDetached("pkill", QStringList() << "-SIGINT" << "-P" << QString::number(m_bash_process->processId()));
    }

    bool runningPrivate()
    {
        if (!m_bash_process)
            return false;

        QProcess process;
        process.setProgram("pgrep");
        process.setArguments(QStringList() << "-P" << QString::number(m_bash_process->processId()));
        process.setProcessChannelMode(QProcess::MergedChannels);

        process.start();

        process.waitForFinished(m_timeout);

        QString pids = QLatin1String(process.readAll());

        QStringList pid_list = pids.split(QRegularExpression("\n"), QString::SkipEmptyParts);

        return (pid_list.size() > 0);
    }

    //Variables
    QPointer<QProcess> m_bash_process;
    int m_timeout;
};

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr) : QMainWindow(parent)
    {
        connect(&m_bash, &Bash::readyRead, this, &MainWindow::readyRead);

        QWidget *central_widget = new QWidget(this);

        QVBoxLayout *layout = new QVBoxLayout(central_widget);
        layout->addWidget(&m_message_board);
        layout->addWidget(&m_cmd_edit);
        layout->addWidget(&m_sigint_btn);

        m_message_board.setReadOnly(true);

        m_cmd_edit.setEnabled(false);

        m_sigint_btn.setText("Send SIGINT(CTRL+C)");

        connect(&m_cmd_edit, &QLineEdit::returnPressed, this, &MainWindow::writeToBash);

        connect(&m_sigint_btn, &QPushButton::clicked, this, &MainWindow::SIGINT);

        setCentralWidget(central_widget);

        resize(640, 480);

        QTimer::singleShot(0, this, &MainWindow::startBash);
    }

    ~MainWindow()
    {
        m_bash.close(); //Not mandatory, called by destructor
    }

private slots:
    void startBash()
    {
        //Open and give to each operation a maximum of 1 second to complete, use -1 to unlimited
        if (m_bash.open(1000))
        {
            m_cmd_edit.setEnabled(true);
            m_cmd_edit.setFocus();
        }
        else
        {
            QMessageBox::critical(this, "Error", "Failed to open bash");
        }
    }

    void writeToBash()
    {
        QString cmd = m_cmd_edit.text();

        m_cmd_edit.clear();

        if (!m_bash.write(cmd))
        {
            QMessageBox::critical(this, "Error", "Failed to write to bash");
        }
    }

    void readyRead(const QString &str)
    {
        m_message_board.appendPlainText(str);
    }

    void SIGINT()
    {
        m_bash.SIGINT();
    }

private:
    Bash m_bash;
    QPlainTextEdit m_message_board;
    QLineEdit m_cmd_edit;
    QPushButton m_sigint_btn;
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

#include "main.moc"
#包括
#包括
#包括
类Bash:公共QObject
{
Q_对象
公众:
显式Bash(QObject*parent=nullptr):QObject(parent)
{
}
~Bash()
{
closePrivate();
}
信号:
无效readyRead(QString);
公众时段:
布尔打开(整数超时=-1)
{
if(m_bash_进程)
返回false;
m_timeout=超时;
返回openPrivate();
}
无效关闭()
{
closePrivate();
}
布尔写入(常量QString&cmd)
{
返回writePrivate(cmd);
}
void SIGINT()
{
SIGINTPrivate();
}
私人:
//功能
bool openPrivate()
{
if(m_bash_进程)
返回false;
m_bash_进程=新的QProcess();
m_bash_进程->设置程序(“/bin/bash”);
//在标准输出通道中合并标准输出和标准输出
m_bash_进程->设置进程通道模式(QProcess::MergedChannel);
连接(m_bash_进程,&QProcess::readyRead,this,&bash::readyReadPrivate);
连接(m_bash_进程、QOverload::of(&QProcess::finished)、this和&bash::closePrivate);
m_bash_进程->开始();
bool started=m_bash_进程->waitForStarted(m_超时);
如果(!已启动)
m_bash_进程->deleteLater();
返回开始;
}
void closePrivate()
{
if(!m_bash_进程)
返回;
m_bash_进程->closeWriteChannel();
m_bash_进程->waitForFinished(m_超时);
m_bash_进程->终止();
m_bash_进程->deleteLater();
}
void readyReadPrivate()
{
if(!m_bash_进程)
返回;
而(m_bash_进程->字节可用()>0)
{
QString str=QLatin1String(m_bash_进程->readAll());
发射readyRead(str);
}
}
bool writePrivate(常量QString&cmd)
{
if(!m_bash_进程)
返回false;
if(runningPrivate())
返回false;
m_bash_进程->写入(cmd.toLatin1());
m_bash_进程->写入(“\n”);
返回m_bash_进程->WaitForBytesWrited(m_超时);
}
void SIGINTPrivate()
{
if(!m_bash_进程)
返回;
QProcess::StartDetailed(“pkill”,QStringList()addWidget(&m_cmd_edit);
布局->添加小部件(&m_sigint_btn);
m_message_board.setReadOnly(真);
m_cmd_edit.setEnabled(false);
m_sigint_btn.setText(“发送sigint(CTRL+C)”);
连接(&m_cmd_edit,&QLineEdit::returnPressed,this,&MainWindow::writeToBash);
连接(&m_sigint_btn,&QPushButton::clicked,this,&main窗口::sigint);
setCentralWidget(中央窗口小部件);
调整大小(640480);
QTimer::singleShot(0、this和main窗口::startBash);
}
~main window()
{
m_bash.close();//不是必需的,由析构函数调用
}
专用插槽:
void startBash()
{
//打开并给每个操作最多1秒的时间来完成,使用-1表示无限
如果(m_bash.open(1000))
{
m_cmd_edit.setEnabled(真);
m_cmd_edit.setFocus();
}
其他的
{
QMessageBox::critical(这是“错误”,“无法打开bash”);
}
}
void writeToBash()
{
QString cmd=m_cmd_edit.text();
m_cmd_edit.clear();
if(!m_bash.write(cmd))
{
QMessageBox::critical(这是“错误”,“无法写入bash”);
}
}
void readyRead(常量QString和str)
{
m_消息板。附加纯文本(str);
}
void SIGINT()
{
m_bash.SIGINT();
}
私人:
巴什穆巴什;
QPlainTextEdit m_留言板;
QLineEdit m_cmd_edit;
QPushButton m_sigint_btn;
};
int main(int argc,char*argv[])
{
质量保证申请a(argc、argv);
主窗口w;
w、 show();
返回a.exec();
}
#包括“main.moc”
我曾经为发布了一个示例。我不确定它是否正是您想要的。为了简单起见,我将(控制台)输入和输出的小部件分开。不过,它可能会为您想要的东西提供一些灵感