Zoom in / Zoom out in QT without using scroll button - qt

I want to zoom in/out a part in openGL using mouse. Now I can do it well using the scroll button in mouse. But my goal is now to perform the same operation by holding the left mouse button and moving the mouse to and fro in the screen.
I don't know how to perform the zooming action by detecting the to and fro motion of mouse.
// function for mouse scroll events
void VDUI_GLWidget::wheelEvent (QWheelEvent * e) {
// here comes the code for zoom in / out based on the scrolling
MouseWheel (e->delta () / float (WHEEL_STEP), QTWheel2VCG (e->modifiers ()));
updateGL();
}
Now I want to perform the same using mouse move and mouse press events. I'm unable to pick the event which detects the to and fro motion

Now I have found the solution. Finding the difference between the current & previous Y axis position, I can zoom in / out the Please refer this below mentioned code.
// function for mouse move events
void GLWidget::mouseMoveEvent (QMouseEvent * e) {
static int curY = 0, prevY = 0;
if (e->buttons()) {
curY = e->y(); // current position of Y
if( (curY - prevY) > 0 ) // call zoom in function
else // call zoom out function
updateGL();
}
prevY = curY;
}

Related

Scrolling sets to top once new data is appended to wijmo-grid in virtual scrolling

While implementing virtual scrolling with wijmo grid, as per the below code, when the new data is appended to data array (once we scroll and reach to the last record of the grid), the scroll gets reset to the initial position.
Check this JSFiddle
scrollPositionChanged: function(s, e) {
// if we're close to the bottom, add 10 items
if (s.viewRange.bottomRow >= s.rows.length - 1) {
addData(data, 20);
s.collectionView.refresh();
}
}
Any idea how can we stop this behaviour? Other grids like slickgrid, ag-grid provides smooth behaviour - once the data is appended, the previous last record stays in the view. Can we achieve similar kind of behaviour for wijmo-grid?
You can save scroll postion before refreshing the grid and restore the same after scroll.
var pos;
var grid = new wijmo.grid.FlexGrid('#flex', {
itemsSource: data,
scrollPositionChanged: function (s, e) {
// if we're close to the bottom, add 10 items
if (s.viewRange.bottomRow >= s.rows.length - 1) {
addData(data, 20);
//save current scroll postion
pos = grid.scrollPosition;
s.collectionView.refresh();
}
//restore scroll position
if (pos) {
s.scrollPosition = Object.assign({}, pos);
pos = null;
}
}
});
Check the updated fiddle:- http://jsfiddle.net/797tjc5u/
You need to store scroll position before making http request and set back once items have been added to FlexGrid.
Please refer to the following updated fiddle with http service delay simulation:
[http://jsfiddle.net/hwr2ra1q/41/][1]

How to get the coordinates of the point that I click?

I am playing with <canvas> tag and just encountered a problem:
https://jsfiddle.net/awguo/6yLqa5hz/
I want to get the coordinates of a point when I click on a canvas.
I searched for a while and found some functions, but as a 300x300 canvas, the point of its right-bottom point is (300,150). Shouldn't it be 300,300 (because the img is 300x300 and the canvas is 100% on it)?
Why?
What should I do to get the 300x300?
You must adjust the event.clientX and event.clientY coordinates returned by your event handlers by the offset of the canvas element vs the window. To do that you can use canvas.getBoundingClientRect to get the left & top canvas offsets. Be sure to listen for resize & scroll events. When those events happen you must re-fetch the canvas's current offset.
// Fetch offsetX & offsetY variables that contain the
// canvas offset versus the window
// Re-fetch when the window is resized or scrolled
function reOffset(){
var BB=canvas.getBoundingClientRect();
offsetX=BB.left;
offsetY=BB.top;
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
Here's how to use the offsets to calculate correct mouse coordinates in an event handler:
function handleMouseDown(e){
// tell the browser we're handling this event
e.preventDefault();
e.stopPropagation();
// calculate the mouse position
mouseX=parseInt(e.clientX-offsetX);
mouseY=parseInt(e.clientY-offsetY);
// your stuff
}
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX,
y: evt.clientY
};
}
Is enough to work. You image is 350px big, not 300px.

Looping ground tile as character moves in unity 2D

I am trying to create a ground tile that, once is off screen moves to the forward position in front of the other ground tile that is currently in the screen.
I have barely tried anything in code that would be even slightly useful to add to this question. Could someone point me in the right direction to be able to get this done so I don't have to just duplicate hundreds of tiles?
Thanks!
Attach this scrip on your Tileobject.
using UnityEngine;
public class SpawnTiles : MonoBehaviour {
private Material currentTile;
public float speed;
private float offset;
// Use this for initialization
void Start () {
currentTile = GetComponent<Renderer>().material;
}
// Update is called once per frame
void Update () {
offset += 0.001f;
currentTile.SetTextureOffset ("_MainTex", new Vector2 (offset * speed, 0));
}
}
Edit
This is what you want?
If YES, follow theses steps.
Create > 3D Object > Quad (Resize as you want)
Select your tile sprite:
Texture type = texture
Wrap mode = repeat
Now creat new Material: Create > Material
Select: Shader = Unlit/Texture
Texture select your previous texture.
Drag and drop this Material inside Quadobject.
Adjust tiles at inspector.
Result
Creat new scrip SpawnTiles and attach at Quadobject.
using UnityEngine;
public class SpawnTiles : MonoBehaviour {
private Material currentTile;
public float speed;
private float offset;
// Update is called once per frame
void Update () {
GetComponent<Renderer>().material.mainTextureOffset = new Vector2 (Time.time * speed, 0f);
}
}
Ajust tiles movement speed at inspector.
Finish rename Quadobject as you want.
If you want to only move the back tile to the front, you probably don't need it, but I still highly suggest looking into object pooling.
To detect if a camera can't see the tile, use this: Renderer.isVisible
To move the tile, if all the tiles are the same dimensions, you could just increase it's position.x by the amount you need.
I have found one solution using WorldPointToViewport().
Here is my script:
using UnityEngine;
using System.Collections;
public class groundTilingScript : MonoBehaviour {
Transform ground; //For reference to the transform
Camera cam; //Reference to Main Camera
float groundWidth; //The width of the transform, used for calculating current max x position of transform and next placement x position
private float nextXPos = 0.0f; //Store next x position in variable for easier reading
// Use this for initialization
void Start () {
//Set up References
ground = transform;
cam = Camera.main;
//Store Ground width (Width of the ground tile)
groundWidth = ground.GetComponent<Renderer> ().bounds.size.x;
}
// Update is called once per frame
void Update () {
//Create new Vector3 to be used in WorldToViewportPoint so it doesn't use the middle of the ground as reference
Vector3 boxRightPos = new Vector3 (ground.position.x + groundWidth/2, ground.position.y, ground.position.z);
//Store view Position of ground
Vector3 viewPos = cam.WorldToViewportPoint (boxRightPos);
//If the ground tile is left of camera viewport
if (viewPos.x < 0) {
//gameObject is offscreen, destroy it and re-instantiate it at new xPosition
float currentRightX = ground.position.x + groundWidth;
nextXPos = currentRightX + groundWidth;
Instantiate (gameObject, new Vector3 (nextXPos, ground.position.y, ground.position.z), ground.rotation);
Destroy (gameObject);
}
}
}
NOTE: I have to set up two ground tiles initially to give room for camera to go further than the ground tile. (One tile on screen, one off)
Again, this is just my attempt. I am completely open to criticism.

Moving object with mouse

I use Qt and I want to move some object with mouse. For example, user clicks on object and drag this object to another place of window. How I can do it?
I tried mouseMoveEvent:
void QDropLabel::mouseMoveEvent(QMouseEvent *ev)
{
this->move(ev->pos());
}
but unfortunately object moves very strange way. It jumps from place to place.
QDropLabel inherits QLabel. Also it has given a pixmap.
I tried to do it with different objects, but result is same.
Your movable widget must have a QPoint offset member. It will store a position of the cursor click relative to the widget's top left corner:
void DropLabel::mousePressEvent(QMouseEvent *event)
{
offset = event->pos();
}
On mouse move event you just move your widget in its parent coordinate system. Note that if you don't subtract offset from the cursor position, your widget will 'jump' so its top left corner will be just under the cursor.
void DropLabel::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons() & Qt::LeftButton)
{
this->move(mapToParent(event->pos() - offset));
}
}

Spark List scrolling by mouse position

<s:List xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
mouseOver="scroller_mouseOver(event)"
height="308" width="110">
As seen above, I have a Spark List with the MouseOver event:
protected function scroller_mouseOver(e:MouseEvent):void {
CursorManager.removeAllCursors(); // Remove all previous Cursors
if (mouseX > 24 && mouseX < 143) {
if (mouseY > 220) {
CursorManager.setCursor(downCursorSymbol); // Down Cursor
} else if (mouseY < 87) {
CursorManager.setCursor(upCursorSymbol); // Up Cursor
}
// Scroll as its Mouse Overed
this.addEventListener(Event.ENTER_FRAME, scrollViaY);
}
}
private function scrollViaY(e:Event):void {
if (mouseX > 24 && mouseX < 143) {
if (mouseY > 220) {
this.layout.verticalScrollPosition += (mouseY - 220)*0.5;
}
else if (mouseY < 87) {
this.layout.verticalScrollPosition += (mouseY -86)*0.5;
}
}
}
The following picture describes the area I would like to track hovering.
The Problem: When I hover the upper (red) part of the List (I would like to have the List scroll downward, the higher the mouse position is, the faster it should scroll). Similarly, If the mouse hovers over the bottom (red) part, the List scrolls upwards, and the lower the mouse is hovered, the faster the list would scroll. The current code does work - Though, the trace outs make it obvious that:
this.layout.verticalScrollPosition += (mouseY - 220)*0.5;
or
this.layout.verticalScrollPosition += (mouseY -86)*0.5;
...are giving jumping effects, is there a way to make these values change more linearly or smoother?
I created an AnimateProperty, but that works well only if I would like to scroll to a selectedIndex, In this case, I would like the scroller to keep scrolling linearly as the mouse is hovered to a particular red area, and increase in speed when I scroll to either extremity.
The Objective: While the mouse is over the Bottom (red part )of the List, the verticalScrollPosition scrolls faster as it gets farther than the center of the ticket list... yet there is jumping effect going on, I suppose due to the EnterFrame. the Same with Upper Part... the higher the cursor is, the faster the List should scroll.
I feel this is a common problem to Flash CSx developers.
I have implemented something similar, except it was a horizontal scrolling list, and also I used a scroll left/right buttons on the sides of the list, the mouse_over effect is triggered by the buttons, not the list (but this shouldn't be an impediment when adapting the code).
To do the actual scrolling, I used an animate effect which targeted the list's layout, and more specifically, the layout's horizontalScrollPosition. This it what the MXML code looks like:
<s:Animate id="scrollAnimation" target="{listLayout}">
<s:easer>
<s:Linear easeInFraction="0" easeOutFraction="0" />
</s:easer>
<s:SimpleMotionPath id="scrollMotionPath" property="horizontalScrollPosition" />
</s:Animate>
That easer is necessary because animate effect usually have 3 motion stages (acceleration, uniform motion and deceleration), so by default you would get a wavy scrolling motion.
I used RobotLeft for that project, so the view is mediated like this:
When the mediator is registered, add the scroll button listeners:
viewComponent.scrollLeft.addEventListener(MouseEvent.MOUSE_OVER, onScrollLeft);
viewComponent.scrollRight.addEventListener(MouseEvent.MOUSE_OVER, onScrollRight);
viewComponent.scrollLeft.addEventListener(MouseEvent.MOUSE_OUT, onScrollOut);
viewComponent.scrollRight.addEventListener(MouseEvent.MOUSE_OUT, onScrollOut);
We also need to add a listener so we can tell when the scrolling effect finished, because we might need to replay it:
viewComponent.scrollEffect.addEventListener(EffectEvent.EFFECT_END, onScrollEnd);
We can now implement the scrolling method. Since the view is mediated, we have access to the scroll effect, we can reference it here (and also the path). This what the method looks like:
private function scrollOnlineFriendsList(scrollBy:int):void
{
// Set the scrollBy value and play the scrolling effect
viewComponent.scrollMotionPath.valueBy = scrollBy;
viewComponent.scrollEffect.play();
// Store the scrollBy value in case the effect will need to be replayed,
// if the mouse over event is still over the scrolling button/area
this.scrollBy = scrollBy;
canKeepScrolling = true;
}
Finally, the handlers:
private function onScrollLeft(event:MouseEvent):void
{
scrollOnlineFriendsList(-33);
}
private function onScrollRight(event:MouseEvent):void
{
scrollOnlineFriendsList(33);
}
private function onScrollOut(event:MouseEvent):void
{
canKeepScrolling = false;
// If you would like the effect to continue playing
// until it finishes the current scrolling operation,
// once the mouse is no longer over a scroll button,
// just comment this line
viewComponent.scrollEffect.stop();
}
private function onScrollEnd(event:EffectEvent):void
{
// When the scroll effect has finished playing,
// if the mouse is still over the scroll button/area,
// replay the effect
if (canKeepScrolling)
scrollOnlineFriendsList(scrollBy);
}

Resources