用Qt实现一个简单的shell (Qt5+V8)
来源:互联网 发布:牛在印度的地位知乎 编辑:程序博客网 时间:2024/04/30 06:54
在CSDN论坛看到有网友问用Qt如何实现一个类似shell的东西。
同时呢,前两天V8已经成为Qt5的基础模块了,刚好,可以做个简单的javascript的shell试试看(只支持单行输入)。
于是,便有了本文。
何处着手?
先用google搜索一下,未找到自己想要的答案(当然,有些比较靠谱的答案:比如去看现有shell(像konsole等)的源码,只是自己懒,不想看)。
初看起来,似乎是个比较简单的东西。
- 用一个只读的控件来显示输入和输出
- 用一个输入控件来接受输入
按照这个思路,加上对shell的期望:
- 选择只读的 QPlainTextEdit 作为主控件
- 用一个 QLineEdit 接受输入
于是:就是下面的效果了,
注意
前两个图,是在Qt5下的结果。(你可以访问V8 初次接触(Qt5)来了解Qt5和V8的关系)
- 第三个图,是Qt4下编译后的结果(没有V8的参与)。
难点?
在贴出源码之前,先提一点这个:
每次等待输入时,都要有提示符,比如">>> "
我们只需要将QLineEdit定位到">>>"这个位置即可
但是,获取这个位置有些困难,为此,动用了 QPlainTextEditPrivate 这个私有类!
源码
分为三个文件
- shelldemo.h
- shelldemo.cpp
- main.cpp
shelldemo.h
创建QPlainTextEdit的派生类
- runCommand() 将输入的命令进行处理,而后输出
- onEditFinished() 响应输出完时的回车
- onScrollBarValueChanged() 滚动条变动时,我们要调整QLineEdit的位置
- resizeEvent() 窗口变化时,我们也要调整QLineEdit的大小和位置
- #ifndef SHELLDEMO_H
- #define SHELLDEMO_H
- #include <QPlainTextEdit>
- class QLineEdit;
- class ShellDemo:public QPlainTextEdit
- {
- Q_OBJECT
- public:
- explicit ShellDemo(QWidget *parent=0);
- virtual QString runCommand(const QString& cmd);
- protected:
- void resizeEvent(QResizeEvent *e);
- private slots:
- void onScrollBarValueChanged();
- void onEditFinished();
- private:
- void updateEditPosition();
- QLineEdit * edit;
- };
- #endif // SHELLDEMO_H
shelldemo.cpp
这个是重点了,你可以忽略其中关于Qt5和V8的代码(已经被宏保住了,不会影响你的编译)。
- #include "shelldemo.h"
- #include <QLineEdit>
- #include <QTextBlock>
- #include <QDebug>
- #include <private/qplaintextedit_p.h>
- #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
- #include <private/v8.h>
- #endif
- ShellDemo::ShellDemo(QWidget *parent) :
- QPlainTextEdit(parent)
- {
- setReadOnly(true);
- QFont font = this->font();
- font.setPointSize(font.pointSize()+2);
- this->setFont(font);
- appendPlainText(">>> ");
- edit = new QLineEdit(this->viewport());
- edit->setStyleSheet("border-style:none; background-color:transparent;");
- connect(edit, SIGNAL(returnPressed()), SLOT(onEditFinished()));
- connect(verticalScrollBar(), SIGNAL(valueChanged(int)), SLOT(onScrollBarValueChanged()));
- }
- void ShellDemo::resizeEvent(QResizeEvent *e)
- {
- updateEditPosition();
- }
- void ShellDemo::onScrollBarValueChanged()
- {
- updateEditPosition();
- }
- QString ShellDemo::runCommand(const QString &cmd)
- {
- #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
- QString output;
- v8::HandleScope handle_scope;
- v8::Persistent<v8::Context> context = v8::Context::New();
- v8::Context::Scope context_scope(context);
- v8::Handle<v8::String> source = v8::String::New(cmd.utf16());
- v8::TryCatch try_catch;
- v8::Handle<v8::Script> script = v8::Script::Compile(source);
- if (script.IsEmpty()) {
- output = QString::fromUtf16(*(v8::String::Value(try_catch.Exception())));
- } else {
- v8::Handle<v8::Value> result = script->Run();
- if (result.IsEmpty()) {
- output = QString::fromUtf16(*(v8::String::Value(try_catch.Exception())));
- } else {
- output = QString::fromUtf16(*(v8::String::Value(result)));
- }
- }
- context.Dispose();
- return output;
- #else
- return QString("Result of %1").arg(cmd);
- #endif
- }
- void ShellDemo::onEditFinished()
- {
- QString cmd = edit->text();
- if (cmd.isEmpty()) {
- return;
- }
- moveCursor(QTextCursor::End);
- insertPlainText(cmd);
- edit->hide();
- edit->clear();
- appendPlainText(runCommand(cmd));
- appendPlainText(">>> ");
- updateEditPosition();
- edit->show();
- edit->setFocus();
- }
- void ShellDemo::updateEditPosition()
- {
- QPlainTextEditPrivate * d = reinterpret_cast<QPlainTextEditPrivate*>(qGetPtrHelper(d_ptr));
- QRectF rect = d->control->blockBoundingRect(d->control->document()->lastBlock());
- edit->move(rect.topRight().toPoint());
- edit->resize(viewport()->size().width(), edit->size().height());
- }
简单说一下:
- updateEditPosition()
用来更新QLineEdit的位置(这里面的代码?你凑活看吧,其实代码还有些问题)。
ShellDemo() 构造函数
基本没做什么。上面设置了大两个点的字体,纯粹是为了舒服一点(不然在我机子上比较难看)。QLineEdit隐藏掉边框,以便和主控件融为一体。
- runCommand()
根据输入,产生什么输出,你说了算。我只是为了学习下V8,胡乱加了点代码。
- onEditFinished()
将输入输出显示到主控件中。
main.cpp
很常规的文件,不用多说。
- #include <QtGui/QtGui>
- #include "shelldemo.h"
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- ShellDemo w;
- w.setWindowTitle("Dbzhang800\'s Qt5 V8-Shell");
- w.show();
- return a.exec();
- }
qt5v8.pro
- .pro 文件很简单,对于Qt5,我们使用了v8模块
contains(QT_VERSION, ^5\\..*\\..*) { QT += v8-private gui-private core-private}SOURCES += main.cpp \ shelldemo.cppHEADERS += \ shelldemo.h \ shellodemo_p.h
后记
- 本例子功能非常不完善,仅供参考
- 用Qt实现一个简单的shell (Qt5+V8)
- 用Qt实现一个简单的shell (Qt5+V8)
- 实现一个简单的shell
- V8 js引擎的一个简单介绍
- 用c语言的实现一个简单的交互式shell
- 关于一个简单的shell的实现
- Qt5实现简单的拼图游戏
- 用Qt creator 实现的第一个qt5小程序
- Linux编程实现一个简单的Shell
- 一个简单地Shell-like 的实现
- 【Linux】实现一个简单的shell
- Linux.实现一个简单的shell
- 【Linux】实现一个简单的shell
- 自主实现一个简单的shell
- QT实现一个简单的计算器
- QT实现一个简单的计算器
- Qt实现一个简单的打字游戏
- 一个简单的shell
- 整理
- Spring MVC 入门
- 树状数组no pain no game(hdu 2013多校contest3)
- C/C++程序编译步骤详解
- 高效利用时间的5个小方法
- 用Qt实现一个简单的shell (Qt5+V8)
- EasyJWeb学习笔记
- 如何实现单一用户单一机子登录
- VC++系统各种路径信息的获取
- 话说程序员的职业生涯
- 软件开发模式对比(瀑布、迭代、螺旋、敏捷)
- sourceInsight使用
- POJ 1971 Parallelogram Counting (Hash)
- jquery的事件总结实用篇(持续更新)