1 背景
Qt5 中有个很基本的单行输入框控件,就是 QLineEdit,类似于HTML中的input标签。
在QCAD开源项目中,其主界面中有个供用户输入绘图命令的单行输入框控件,其可以实现类似 Linux 终端的简单效果:
- 上键显示最近的一条命令
- 上下键在历史命令里面查找命令
- Ctrl+V键粘贴命令
- Ctrl+L键清空命令
功能简单,但是也算是看到了 Qt 的较中级的用法,就是继承和扩展Qt 原生组件。
2 代码说明
首先继承 QLineEdit 类。
新增了两个字段/属性,用于存储命令的字符串列表 history,还有一个迭代器 it,指代命令在列表中的位置。
重载 keyPressEvent 函数,用于支持自定义的Up,Down,Ctrl+V,Ctrl+L按键事件。
注意:源代码非完整代码,无法运行。
3 源代码
3.1 头文件 RCommandLine.h
/**
* Copyright (c) 2011-2018 by Andrew Mustun. All rights reserved.
*
* This file is part of the QCAD project.
*
* QCAD is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* QCAD is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with QCAD.
*/
#ifndef RCOMMANDLINE_H_
#define RCOMMANDLINE_H_
#include "gui_global.h"
#include <QEvent>
#include <QLineEdit>
#include <QMetaType>
#include <QStringList>
/**
* \scriptable
* \ingroup gui
*/
class QCADGUI_EXPORT RCommandLine: public QLineEdit {
Q_OBJECT
signals:
void clearHistory();
void commandConfirmed(const QString& command);
void completeCommand(const QString& command);
void escape();
public:
RCommandLine(QWidget* parent = 0);
QString getLastCommand();
void appendCommand(const QString& cmd);
QStringList getHistory() const;
void setHistory(QStringList& h);
void triggerCommand(const QString& cmd) {
emit commandConfirmed(cmd);
}
public slots:
void paste();
protected:
virtual void keyPressEvent(QKeyEvent* event);
virtual bool event(QEvent* event);
private:
QStringList history;
QStringList::iterator it;
};
Q_DECLARE_METATYPE(RCommandLine*)
#endif
3.2 RCommandLine.cpp
/**
* Copyright (c) 2011-2018 by Andrew Mustun. All rights reserved.
*
* This file is part of the QCAD project.
*
* QCAD is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* QCAD is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with QCAD.
*/
#include <QClipboard>
#include <QDebug>
#include <QEvent>
#include <QKeyEvent>
#if QT_VERSION >= 0x050000
#include <QGuiApplication>
#else
#include <QApplication>
#endif
#include "RCommandLine.h"
#include "RDebug.h"
RCommandLine::RCommandLine(QWidget* parent) :
QLineEdit(parent), it(history.end()) {
}
QString RCommandLine::getLastCommand() {
if (history.isEmpty()) {
return QString();
}
return history.last();
}
void RCommandLine::appendCommand(const QString& cmd) {
if (!cmd.isEmpty() && (history.isEmpty() || history.last() != cmd)) {
history.append(cmd);
}
it = history.end();
}
QStringList RCommandLine::getHistory() const {
return history;
}
void RCommandLine::setHistory(QStringList& h) {
history = h;
it = history.end();
}
void RCommandLine::paste() {
#if QT_VERSION >= 0x050000
QClipboard* cb = QGuiApplication::clipboard();
#else
QClipboard* cb = QApplication::clipboard();
#endif
//qDebug("pasting: " + cb.text());
QString text = cb->text();
// multi line paste and enter:
if (text.contains("\n")) {
QStringList lines = text.split('\n');
for (int i=0; i<lines.length(); i++) {
//qDebug("line: " + lines[i]);
emit commandConfirmed(lines[i]);
}
}
else {
// single line paste only:
QLineEdit::paste();
}
}
bool RCommandLine::event(QEvent* event) {
if (event->type() == QEvent::KeyPress) {
QKeyEvent* ke = dynamic_cast<QKeyEvent*> (event);
if (ke->key() == Qt::Key_Tab) {
emit completeCommand(text());
return true;
}
}
return QLineEdit::event(event);
}
void RCommandLine::keyPressEvent(QKeyEvent* event) {
switch (event->key()) {
case Qt::Key_L:
if (event->modifiers() == Qt::ControlModifier) {
emit clearHistory();
return;
}
break;
case Qt::Key_V:
if (event->modifiers() == Qt::ControlModifier) {
paste();
return;
}
break;
case Qt::Key_Enter:
case Qt::Key_Return: {
QString t = text();
// if (!t.isEmpty() && (history.isEmpty() || history.last() != t)) {
// history.append(t);
// }
it = history.end();
emit commandConfirmed(t);
}
break;
case Qt::Key_Up:
if (it != history.begin()) {
it--;
setText(*it);
}
return;
break;
case Qt::Key_Down:
if (it != history.end()) {
it++;
if (it != history.end()) {
setText(*it);
} else {
clear();
}
}
return;
break;
default:
break;
}
QLineEdit::keyPressEvent(event);
}
以上源代码仅供学习交流,版权归QCAD项目所有。