Qt QML如何通过双击在文本区域中手动选择单词
双击选择单词,但我想定制它,例如,选择1000美元的术语 例如:Qt QML如何通过双击在文本区域中手动选择单词,qt,qml,Qt,Qml,双击选择单词,但我想定制它,例如,选择1000美元的术语 例如: import QtQuick 2.7 import QtQuick.Controls 1.4 ApplicationWindow { visible: true width: 640 height: 480 TextArea { anchors.fill: parent text: "hello, try to select the $1000 prize
import QtQuick 2.7
import QtQuick.Controls 1.4
ApplicationWindow
{
visible: true
width: 640
height: 480
TextArea
{
anchors.fill: parent
text: "hello, try to select the $1000 prize!"
font.pointSize: 14
}
}
例如,通过某种方式覆盖selectWord
或覆盖双击的onDoubleClicked
或通过某种方式添加我自己的MouseArea
,这不会破坏现有的TextArea
功能
不知道怎么做
谢谢你的帮助
更新
我尝试添加了一个MouseArea
,但没有成功。榜样
ApplicationWindow
{
visible: true
width: 640
height: 480
TextArea
{
anchors.fill: parent
text: "hello, try to select the $1000 prize!"
font.pointSize: 14
MouseArea
{
anchors.fill: parent
propagateComposedEvents: true
onClicked:
{
// attempt to get an event on click without
// affecting the TextArea. But it breaks selection.
console.log("clicked some text")
mouse.accepted = false
}
}
}
}
更新2
我认为这个问题是长时间运行的Qt问题的一个版本,你不能有某种“事件观察者”,其工作是检查事件,但不阻止它们继续正常运行
如果我有一个事件观察者,我可以让它“观察”文本区域,然后单击或双击做一些事情
所以,现在我们要做一个
接触面积
#pragma once
#include <QGuiApplication>
#include <QQuickItem>
#include <QTime>
class TouchArea : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QQuickItem *target READ target WRITE setTarget NOTIFY targetChanged)
public:
QTime _lastMousePress;
int _clickThresholdMS = 300;
bool eventFilter(QObject*, QEvent *event) override
{
// if false this will allow the event to continue as normal
// if true it will stop the event propagating
bool handled = false;
// https://doc.qt.io/qt-5/qevent.html#Type-enum
QEvent::Type t = event->type();
switch (t)
{
case QEvent::TouchUpdate:
break;
case QEvent::KeyPress:
case QEvent::KeyRelease:
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
qDebug("key press %d", keyEvent->key());
}
break;
case QEvent::MouseButtonPress:
{
qDebug() << "mouse press";
_lastMousePress.start();
break;
}
case QEvent::MouseButtonRelease:
{
qDebug() << "mouse release";
int dt = _lastMousePress.elapsed();
if (dt < _clickThresholdMS)
{
qDebug() << "mouse click";
emit clicked();
}
break;
}
}
return handled;
}
QQuickItem *target() const { return _target; }
void setTarget(QQuickItem *target)
{
qDebug() << "set target";
if (_target == target) return;
if (_target)
_target->removeEventFilter(this);
_target = target;
if (_target)
_target->installEventFilter(this);
emit targetChanged();
}
signals:
void targetChanged();
void clicked();
private:
QQuickItem* _target = 0;
};
嗯,这几乎奏效了。只有在eventFilter
中处理了eventFilter
事件时,我才能捕获我的合成点击。当未处理时
过滤器看不到鼠标按钮释放
这是为什么。我希望这是在其他QtQuick项目看到它之前遇到的第一个处理程序
有什么帮助吗?我想不出任何解决方案可以保留
TextArea
行为,就在QML方面。我将尝试在C++端包装、继承或重新实现组件,添加您想要的。
- 继承可能很棘手,因为很少有Qt类是直接继承的,查看
和QQuickTextArea
源代码,这可能是一个挑战qquicktextededit
- 重新实现可能是一项工作,但这可能是我的选择,同时将逻辑和代码保持在最低限度
似乎是一个很好的基础/参考,因为它比QQuickTextArea
更小/更简单(后者反过来在内部使用TextArea)QQuickTextArea
- 事件管理(鼠标、选择等)
- 基于Qt OpenGL包装类(QSG*场景图类)的组件渲染。这有点晦涩,但是有一些教程和演示。您可以复制粘贴原始代码
:QQuickTextEdit
:QQuickTextArea
- 想出了一个办法
步骤1,定义事件的观察者类
观察员h
#pragma once
#include <QGuiApplication>
#include <QQuickItem>
#include <QTime>
#include <QMouseEvent>
class Observer : public QQuickItem
{
Q_OBJECT
public:
QTime _lastMousePress;
int _clickThresholdMS = 300;
Observer()
{
setFiltersChildMouseEvents(true);
}
bool childMouseEventFilter(QQuickItem*, QEvent *event) override
{
// if false this will allow the event to continue as normal
// if true it will stop the event propagating
bool handled = false;
// https://doc.qt.io/qt-5/qevent.html#Type-enum
QEvent::Type t = event->type();
switch (t)
{
case QEvent::TouchUpdate:
break;
case QEvent::KeyPress:
case QEvent::KeyRelease:
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
qDebug("key press %d", keyEvent->key());
}
break;
case QEvent::MouseButtonPress:
{
//qDebug() << "mouse press";
_lastMousePress.start();
}
break;
case QEvent::MouseButtonRelease:
{
//qDebug() << "mouse release";
int dt = _lastMousePress.elapsed();
if (dt < _clickThresholdMS)
{
//qDebug() << "mouse click";
emit clicked();
}
}
break;
case QEvent::MouseButtonDblClick:
{
//QMouseEvent* mevent = static_cast<QMouseEvent*>(event);
//qDebug() << "mouse double click";
emit doubleClicked();
handled = true;
}
break;
}
return handled;
}
signals:
void clicked();
void doubleClicked();
};
看起来您可以使用以下工具执行此操作:
导入QtQuick 2.15
导入QtQuick.Controls 2.15
文本字段{
宽度:parent.width
selectByMouse:true
塔普汉德尔{
grabPermissions:PointerHandler.TakeOverForbidden
onDoubleTapped:(事件点)=>{
打印(“taptap”);
eventPoint.accepted=true;
}
}
}
请注意,我经历了在
TextField
上双击=选择字符串在上述两种情况下都不起作用。单击并拖动以选择“始终有效”。您是否尝试先搜索它?@folibis当然,但它没有指示如何覆盖双击或其他操作。如果我添加自己的MouseArea
,则TextArea
中断。您应该澄清您的问题,因为此评论完全改变了question@folibis你说得对。我补充了我到目前为止所尝试的。谢谢你的回答。不幸的是,我使用的是TextArea
1.4,因为我需要的是controls2中没有的剪切粘贴对话框。我尝试在中复制并更改QML源,但私人部分太多。我有一个不同的C++方法。但是它不起作用。哦,很好,我不认为您能够正确捕获/释放复杂对象(如文本词)上的事件。干得好
import QtQuick 2.12
import QtQuick.Controls 1.4
import App 1.0
ApplicationWindow
{
visible: true
width: 640
height: 480
TextArea
{
id: tarea
anchors.fill: parent
text: "hello, try to select the $1000 prize!"
font.pointSize: 14
MouseArea
{
enabled: false
anchors.fill: parent
TouchArea
{
target: parent
onClicked: console.log("captured a click")
}
}
}
}
#pragma once
#include <QGuiApplication>
#include <QQuickItem>
#include <QTime>
#include <QMouseEvent>
class Observer : public QQuickItem
{
Q_OBJECT
public:
QTime _lastMousePress;
int _clickThresholdMS = 300;
Observer()
{
setFiltersChildMouseEvents(true);
}
bool childMouseEventFilter(QQuickItem*, QEvent *event) override
{
// if false this will allow the event to continue as normal
// if true it will stop the event propagating
bool handled = false;
// https://doc.qt.io/qt-5/qevent.html#Type-enum
QEvent::Type t = event->type();
switch (t)
{
case QEvent::TouchUpdate:
break;
case QEvent::KeyPress:
case QEvent::KeyRelease:
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
qDebug("key press %d", keyEvent->key());
}
break;
case QEvent::MouseButtonPress:
{
//qDebug() << "mouse press";
_lastMousePress.start();
}
break;
case QEvent::MouseButtonRelease:
{
//qDebug() << "mouse release";
int dt = _lastMousePress.elapsed();
if (dt < _clickThresholdMS)
{
//qDebug() << "mouse click";
emit clicked();
}
}
break;
case QEvent::MouseButtonDblClick:
{
//QMouseEvent* mevent = static_cast<QMouseEvent*>(event);
//qDebug() << "mouse double click";
emit doubleClicked();
handled = true;
}
break;
}
return handled;
}
signals:
void clicked();
void doubleClicked();
};
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <qqmlcontext.h>
#include "observer.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<Observer>("App", 1, 0, "Observer");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
import QtQuick 2.12
import QtQuick.Controls 1.4
import App 1.0
ApplicationWindow
{
visible: true
width: 640
height: 480
Observer
{
anchors.fill: parent
onDoubleClicked:
{
tarea.selectWord();
var s = tarea.selectionStart
var e = tarea.selectionEnd
function allowed(c)
{
if (c == "$" || c == "#") return true;
if (c >= "0" && c <= "9") return true;
if (c.toUpperCase() != c.toLowerCase()) return true;
return false;
}
while (allowed(tarea.getText(s-1, s))) tarea.select(--s, e);
while (allowed(tarea.getText(e, e+1))) tarea.select(s, ++e);
}
TextArea
{
id: tarea
anchors.fill: parent
text: "hello, try to select the #$$$1000###$foo prize!"
font.pointSize: 14
}
}
}