提示:本文为学习记录,若有错误,请联系作者,谦虚受教。
文章目录
前言
Constant dropping wears the stone.
一、头文件
cpp
#ifndef TERMINALWIDGET_H
#define TERMINALWIDGET_H
#include <QTextEdit>
#include <QKeyEvent>
#include <QFont>
#include <QProcess>
#include <QByteArray>
#include <QLabel>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QTextLayout>
#include <QTextCursor>
#include <QTextBlock>
#include <QTextCodec>
#include <assert.h>
class TerminalWidget: public QTextEdit
{
Q_OBJECT
public:
TerminalWidget();
protected:
void keyPressEvent(QKeyEvent *e);
private:
// 字体
QFont font;
// 命令行终端进程
QProcess * proc;
// 光标位置
long long lastPosition = 0;
// 上一次的输入内容
QByteArray lastInput;
public slots:
/**
* @brief readyReadStandardOutputSlot 标准输出
*/
void readyReadStandardOutputSlot();
/**
* @brief readyReadStandardErrorSlot 错误输出
*/
void readyReadStandardErrorSlot();
};
#endif // TERMINALWIDGET_H
二、cpp文件
cpp
#include "terminalwidget.h"
#include <QDebug>
TerminalWidget::TerminalWidget()
{
setStyleSheet("background-color:rgb(0,0,0); color:rgb(255,255,255); border:0px;");
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
resize(1000,700);
setWindowTitle("命令行提示符");
font.setFamily("Times New Roman");
font.setPixelSize(14);
setFont(font);
proc = new QProcess();
connect(proc,SIGNAL(readyReadStandardOutput()),this,SLOT(readyReadStandardOutputSlot()));
connect(proc,SIGNAL(readyReadStandardError()),this,SLOT(readyReadStandardErrorSlot()));
#ifdef Q_OS_WIN
proc->start("cmd");
#elif Q_OS_LINUX
proc->start("bash");
#endif
QTextCursor editCursor = textCursor();
QTextBlockFormat textBlockFormat;
textBlockFormat.setLineHeight(20, QTextBlockFormat::FixedHeight);
editCursor.setBlockFormat(textBlockFormat);
setTextCursor(editCursor);
}
void TerminalWidget::keyPressEvent(QKeyEvent *e)
{
QTextCursor editCursor = textCursor();
// Qt::Key_Enter 是小键盘(数字键盘)的 Enter,对应的虚拟键码为:0x01000005
// Qt::Key_Return 是大键盘区的 Enter,对应的虚拟键码为:0x01000004
if(e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter)
{
e->ignore();
editCursor.setPosition(lastPosition, QTextCursor::MoveAnchor);
editCursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
QString string = editCursor.selectedText();
editCursor.clearSelection();
#ifdef Q_OS_WIN
lastInput = string.toLocal8Bit() + '\r' + '\n';
#elif Q_OS_LINUX
lastInput = string.toLocal8Bit() + '\n';
#endif
proc->write(lastInput);
return;
}
else if(e->key() == Qt::Key_Backspace && editCursor.position() <= lastPosition)
return;
else if(e->key() == Qt::Key_Delete && editCursor.position() <= lastPosition)
return;
else
return QTextEdit::keyPressEvent(e);
}
void TerminalWidget::readyReadStandardOutputSlot()
{
QByteArray ba = proc->readAllStandardOutput();
QTextCodec * textCodec = QTextCodec::codecForName("System");
// assert 断言,如果 textCodec 为空,则编译报错
assert(textCodec != nullptr);
QString output = textCodec->toUnicode(ba);
if (output.length() > 0 && output != QString::fromLocal8Bit(lastInput))
{
setTextColor(Qt::white);
append(output.trimmed());
moveCursor(QTextCursor::End);
lastPosition = textCursor().position();
}
}
void TerminalWidget::readyReadStandardErrorSlot()
{
QByteArray ba = proc->readAllStandardError();
QTextCodec* textCodec = QTextCodec::codecForName("System");
// assert 断言,如果 textCodec 为空,则编译报错
assert(textCodec != nullptr);
QString output = textCodec->toUnicode(ba);
if (output.length() > 0 && output != QString::fromLocal8Bit(lastInput))
{
setTextColor(Qt::red);
append(output.trimmed());
moveCursor(QTextCursor::End);
lastPosition = textCursor().position();
}
}
三、使用流程
主要使用process来命令行操作
代码如下(示例):
c
int main(int argc,char *argv[])
{
QAPPlication a(argc,argv);
TerminalWidget w;
w.show();
return a,exec();
}
如图所示
总结
善于总结,多进一步。