1 背景

Qt5 中有个很基本的单行输入框控件,就是 QLineEdit,类似于HTML中的input标签。

QCAD开源项目中,其主界面中有个供用户输入绘图命令的单行输入框控件,其可以实现类似 Linux 终端的简单效果:

  1. 上键显示最近的一条命令
  2. 上下键在历史命令里面查找命令
  3.  Ctrl+V键粘贴命令
  4.  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项目所有。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐