После тщательного прочтения документации я пришел к выводу, что невозможно выйти за пределы сцены. Тем не менее, можно вручную установить пределы сцены на нечто большее, чем фактическая сцена. Самое простое решение состоит в том, чтобы установить достаточно большую сцену в начале, как предложено здесь . Однако это не динамично и имеет ограничения. Я решил эту проблему путем автоматического вычисления пределов сцены при каждом обновлении сцены. Для этого я подключаю QGraphicsScene::changed
к слоту, в котором вычисляется автоматический размер сцены, и вручную заставляю сцену обновляться движением мыши. Последний класс с желаемым поведением:
Заголовок
#ifndef CUSTOMGRAPHICSVIEW_H
#define CUSTOMGRAPHICSVIEW_H
#include
class CustomGraphicsView : public QGraphicsView
{
Q_OBJECT
public:
CustomGraphicsView(QWidget* parent = nullptr);
protected:
virtual void wheelEvent(QWheelEvent* event) override;
virtual void mouseMoveEvent(QMouseEvent* event) override;
virtual void mousePressEvent(QMouseEvent* event) override;
virtual void mouseReleaseEvent(QMouseEvent* event) override;
void autocomputeSceneSize(const QList& region);
};
#endif // CUSTOMGRAPHICSVIEW_H
CPP
#include "customview.h"
#include
CustomGraphicsView::CustomGraphicsView(QWidget* parent) : QGraphicsView(parent)
{
// Set up new scene
setScene(new QGraphicsScene);
// Do not show scroll bars
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// Connect scene update to autoresize
connect(scene(), &QGraphicsScene::changed, this, &CustomGraphicsView::autocomputeSceneSize);
}
void CustomGraphicsView::wheelEvent(QWheelEvent* event)
{
// if ctrl pressed, use original functionality
if (event->modifiers() & Qt::ControlModifier)
QGraphicsView::wheelEvent(event);
// Rotate scene
else if (event->modifiers() & Qt::ShiftModifier)
{
if (event->delta() > 0)
{
rotate(1);
}
else
{
rotate(-1);
}
}
// Zoom
else
{
ViewportAnchor previous_anchor = transformationAnchor();
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
if (event->delta() > 0)
{
scale(1.1, 1.1);
}
else
{
scale(0.9, 0.9);
}
setTransformationAnchor(previous_anchor);
}
}
void CustomGraphicsView::mouseMoveEvent(QMouseEvent* event)
{
QGraphicsView::mouseMoveEvent(event);
if (event->buttons() & Qt::LeftButton)
// If we are moveing with the left button down, update the scene to trigger autocompute
scene()->update(mapToScene(rect()).boundingRect());
}
void CustomGraphicsView::mousePressEvent(QMouseEvent* event)
{
if (event->buttons() & Qt::LeftButton)
// Set drag mode when left button is pressed
setDragMode(QGraphicsView::ScrollHandDrag);
QGraphicsView::mousePressEvent(event);
}
void CustomGraphicsView::mouseReleaseEvent(QMouseEvent* event)
{
if (dragMode() & QGraphicsView::ScrollHandDrag)
// Unset drag mode when left button is released
setDragMode(QGraphicsView::NoDrag);
QGraphicsView::mouseReleaseEvent(event);
}
void CustomGraphicsView::autocomputeSceneSize(const QList& region)
{
Q_UNUSED(region);
// Widget viewport recangle
QRectF widget_rect_in_scene(mapToScene(-20, -20), mapToScene(rect().bottomRight() + QPoint(20, 20)));
// Copy the new size from the old one
QPointF new_top_left(sceneRect().topLeft());
QPointF new_bottom_right(sceneRect().bottomRight());
// Check that the scene has a bigger limit in the top side
if (sceneRect().top() > widget_rect_in_scene.top())
new_top_left.setY(widget_rect_in_scene.top());
// Check that the scene has a bigger limit in the bottom side
if (sceneRect().bottom() < widget_rect_in_scene.bottom())
new_bottom_right.setY(widget_rect_in_scene.bottom());
// Check that the scene has a bigger limit in the left side
if (sceneRect().left() > widget_rect_in_scene.left())
new_top_left.setX(widget_rect_in_scene.left());
// Check that the scene has a bigger limit in the right side
if (sceneRect().right() < widget_rect_in_scene.right())
new_bottom_right.setX(widget_rect_in_scene.right());
// Set new scene size
setSceneRect(QRectF(new_top_left, new_bottom_right));
}
Sure, how about:
They all seem to be a bit work in progress, but work to some degree. They are also similar to XPath and XQuery conceptually; even though XML and JSON have different conceptual models (hierarchic vs object/struct).
EDIT Sep-2015: Actually there is now JSON Pointer standard that allows very simple and efficient traversal of JSON content. It is not only formally specified, but also supported by many JSON libraries. So I would call it actual real useful standard, although due to its limited expressiveness it may or may not be considered Query Language per se.
Текущая реализация Jaql нацелена на обработку больших данных с использованием кластера Hadoop, поэтому это может быть больше, чем нужно. Тем не менее, он легко запускается без кластера Hadoop (но все же для его компиляции требуется код Hadoop и его зависимости, которые в основном включены). Небольшая реализация Jaql, которая может быть встроена в Javascript и в браузер, станет отличным дополнением к проекту.
Ваши примеры выше легко написаны на jaql:
$data = [{"x": 2, "y": 0}, {"x": 3, "y": 1}, {"x": 4, "y": 1}];
$data -> filter $.y > 0 -> transform $.x -> sum(); // 7
$data -> filter $.y > 0 -> transform $.x; // [3,4]
Конечно, есть и многое другое. Например:
// Compute multiple aggregates and change nesting structure:
$data -> group by $y = $.y into { $y, s:sum($[*].x), n:count($), xs:$[*].x};
// [{ "y": 0, "s": 2, "n": 1, "xs": [2] },
// { "y": 1, "s": 7, "n": 2, "xs": [3,4] }]
// Join multiple data sets:
$more = [{ "y": 0, "z": 5 }, { "y": 1, "z": 6 }];
join $data, $more where $data.y == $more.y into {$data, $more};
// [{ "data": { "x": 2, "y": 0 }, "more": { "y": 0, "z": 5 }},
// { "data": { "x": 3, "y": 1 }, "more": { "y": 1, "z": 6 }},
// { "data": { "x": 4, "y": 1 }, "more": { "y": 1, "z": 6 }}]
Jaql можно скачать / обсудить по адресу http://code.google.com/p/jaql/
Я остановлюсь на идее простого использования вашего собственного javascript, но для чего-то более сложного вы можете взглянуть на данные dojo . Не использовал его, но, похоже, он дает вам примерно тот интерфейс запросов, который вы ищете.
Если вы используете .NET, то Json.NET поддерживает запросы LINQ поверх JSON. Эта запись имеет несколько примеров. Он поддерживает фильтрацию, отображение, группировку и т. Д.
I ' Рекомендую мой проект, над которым я работаю, под названием jLinq . Я жду отзывов, поэтому мне было бы интересно услышать, что вы думаете.
Если позволяет вам писать запросы, аналогичные тем, которые вы делаете в LINQ ...
var results = jLinq.from(records.users)
//you can join records
.join(records.locations, "location", "locationId", "id")
//write queries on the data
.startsWith("firstname", "j")
.or("k") //automatically remembers field and command names
//even query joined items
.equals("location.state", "TX")
//and even do custom selections
.select(function(rec) {
return {
fullname : rec.firstname + " " + rec.lastname,
city : rec.location.city,
ageInTenYears : (rec.age + 10)
};
});
Это также полностью расширяемо!
Документация все еще в процессе,