Display Mouse Coordinates Near Mouse as Hints on Mouse Move

Display mouse coordinates near mouse as hints on mouse move

JFreeChart has quite flexible support for crosshairs. To do what you described I would use an Overlay on the ChartPanel, and update the crosshairs from your ChartMouseListener. Here is a self-contained example (which I'll add to the collection of demos that we ship with the JFreeChart Developer Guide):

package org.jfree.chart.demo;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.panel.CrosshairOverlay;
import org.jfree.chart.plot.Crosshair;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.general.DatasetUtilities;
import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.jfree.ui.RectangleEdge;

/**
* A demo showing crosshairs that follow the data points on an XYPlot.
*/
public class CrosshairOverlayDemo1 extends JFrame implements ChartMouseListener {

private ChartPanel chartPanel;

private Crosshair xCrosshair;

private Crosshair yCrosshair;

public CrosshairOverlayDemo1(String title) {
super(title);
setContentPane(createContent());
}

private JPanel createContent() {
JFreeChart chart = createChart(createDataset());
this.chartPanel = new ChartPanel(chart);
this.chartPanel.addChartMouseListener(this);
CrosshairOverlay crosshairOverlay = new CrosshairOverlay();
this.xCrosshair = new Crosshair(Double.NaN, Color.GRAY, new BasicStroke(0f));
this.xCrosshair.setLabelVisible(true);
this.yCrosshair = new Crosshair(Double.NaN, Color.GRAY, new BasicStroke(0f));
this.yCrosshair.setLabelVisible(true);
crosshairOverlay.addDomainCrosshair(xCrosshair);
crosshairOverlay.addRangeCrosshair(yCrosshair);
chartPanel.addOverlay(crosshairOverlay);
return chartPanel;
}

private JFreeChart createChart(XYDataset dataset) {
JFreeChart chart = ChartFactory.createXYLineChart("Crosshair Demo",
"X", "Y", dataset);
return chart;
}

private XYDataset createDataset() {
XYSeries series = new XYSeries("S1");
for (int x = 0; x < 10; x++) {
series.add(x, x + Math.random() * 4.0);
}
XYSeriesCollection dataset = new XYSeriesCollection(series);
return dataset;
}

@Override
public void chartMouseClicked(ChartMouseEvent event) {
// ignore
}

@Override
public void chartMouseMoved(ChartMouseEvent event) {
Rectangle2D dataArea = this.chartPanel.getScreenDataArea();
JFreeChart chart = event.getChart();
XYPlot plot = (XYPlot) chart.getPlot();
ValueAxis xAxis = plot.getDomainAxis();
double x = xAxis.java2DToValue(event.getTrigger().getX(), dataArea,
RectangleEdge.BOTTOM);
double y = DatasetUtilities.findYValue(plot.getDataset(), 0, x);
this.xCrosshair.setValue(x);
this.yCrosshair.setValue(y);
}

public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
CrosshairOverlayDemo1 app = new CrosshairOverlayDemo1(
"JFreeChart: CrosshairOverlayDemo1.java");
app.pack();
app.setVisible(true);
}
});
}

}

Moving the mouse according to the given coordinates

This is a quick and rather dirty solution:

Let's start with a few varibles:

 List<Point> points = null;
Timer tt = null;
int index = 0;

Now a button to start the recoding; it initializes a List<Point> to collect the positions and creates and starts a Timer along with lambda code to do the recoding in the Timer.Tick event:

private void btn_Record_Click(object sender, EventArgs e)
{
points = new List<Point>();
index = 0;
tt = new Timer()
{ Interval = 50, Enabled = true };
tt.Tick += (ss, ee) =>
{
if (!points.Any() || points.Last() != Control.MousePosition)
points.Add(Control.MousePosition);
};
}

Next a button to stop recording:

private void btn_Stop_Click(object sender, EventArgs e)
{
if (tt!=null) tt.Stop();
}

Finally the replay button; it uses an index to loop over the the points collection in a new Timer.Tick code but using the same timer:

private void btn_Replay_Click(object sender, EventArgs e)
{
index = 0;
tt = new Timer() { Interval = 50, Enabled = true };
tt.Tick += (ss, ee) =>
{
if (index < points.Count)
{ System.Windows.Forms.Cursor.Position = points[index++]; }
else tt.Stop();
}

A few notes:

  • As asked in the question this will record and reply the Mmouse coodinates. It will do so in fixed intervals, so playback will look very similar to the original movements; in fact it is so hard to tell apart that I added a slowmo button with a longer interval to demonstrate.. (But the gif got too large)

  • The code will record the mouse positions in screen coordinates and should capture them wherever it goes, not only inside your application. See how VS is activating the code loupe!

  • It will not record any other mouse events, like up, down, click, doubleclick or wheel. For those you would need a global mouse hook for capturing and some external calls for replaying.

  • For including other mouse events you would also need a different and extended data structure; and you would also have to go from a timer-driven model to a mouse event driven one.

  • The example uses buttons to start and stop. Of course the movenments to and from those buttons get included in the recorded list of positions. Instead one could use a timed start, which would start recording after a few seconds and stop recording after a few seconds of inactivity..

There are various ways you can save and load the points; the simplest one is to serialize to xml; using a string path = @"..." it could look as simple as this:

private void btn_save_Click(object sender, EventArgs e)
{
if (points == null) points = new List<Point>();
XmlSerializer xs = new XmlSerializer((points).GetType());
using (TextReader tr = new StreamReader(path))
{
points = (List<Point>)xs.Deserialize(tr);
tr.Close();
}
}

private void btn_load_Click(object sender, EventArgs e)
{
XmlSerializer xs = new XmlSerializer((points).GetType());
using (TextWriter tw = new StreamWriter(path))
{
xs.Serialize(tw, points);
tw.Close();
}
}

Other ways would be using a binary formatter or a custom conversion routine. Xml is relatively stable.

Here is a short clip:

Sample Image

Get mouse coordinates when mouse stop or change direction

var timer, timer2 = 0, client_x, client_y; //I made them global since it's easier
$("#container").mousemove( function(e) {
clearTimeout(timer);
client_x = e.pageX;
client_y = e.pageY;
if((new Date()).getTime() > timer2 + 2000) {
timer2 = (new Date()).getTime(); //just in case this event handler gets called again before the timer runs doCopy
setTimeout(doCopy, 1); //run "outside" the event handler (since it's not good for an event handler to take a long time
} else {
timer = setTimeout(doCopy, 1000);
}
});

function doCopy() {
timer2 = (new Date()).getTime();
.....
}

This is constantly settings and clearing timers. If the mouse stops for 1 second the doCopy() function gets triggered.

How to print out 'Live' mouse position coordinates using pyautogui?

Code :

import pyautogui
pyautogui.displayMousePosition()

Here is some output :

Press Ctrl-C to quit.
X: 0 Y: 1143 RGB: ( 38, 38, 38)

Here is the video where this is being demonstrated https://youtu.be/dZLyfbSQPXI?t=809

Find mouse position relative to element

For people using JQuery:

Sometimes, when you have nested elements, one of them with the event attached to it, it can be confusing to understand what your browser sees as the parent. Here, you can specify which parent.

You take the mouse position, and then subtract it from the parent element's offset position.

var x = evt.pageX - $('#element').offset().left;
var y = evt.pageY - $('#element').offset().top;

If you're trying to get the mouse position on a page inside a scrolling pane:

var x = (evt.pageX - $('#element').offset().left) + self.frame.scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + self.frame.scrollTop();

Or the position relative to the page:

var x = (evt.pageX - $('#element').offset().left) + $(window).scrollLeft();
var y = (evt.pageY - $('#element').offset().top) + $(window).scrollTop();

Note the following performance optimisation:

var offset = $('#element').offset();
// Then refer to
var x = evt.pageX - offset.left;

In this way, JQuery does not have to look up #element for each line.

Update

There is a newer, JavaScript-only version in an answer by @anytimecoder -- see also browser support for getBoundingClientRect().

How to show live mouse position on tkinter window

You can use after() to periodically get the mouse coordinates and update the label.

Below is an example:

import tkinter as tk
import win32api

root = tk.Tk()

mousecords = tk.Label(root)
mousecords.place(x=0, y=0)

def show_mouse_pos():
x, y = win32api.GetCursorPos()
#x, y = mousecords.winfo_pointerxy() # you can also use tkinter to get the mouse coords
mousecords.config(text=f'x : {x}, y : {y}')
mousecords.after(50, show_mouse_pos) # call again 50ms later

show_mouse_pos() # start the update task
root.mainloop()


Related Topics



Leave a reply



Submit