Open Template Popup at Mouse Location

Good morning, I’m having issues with a script and wonder if someone had any ideas.

What I have is a template with a button, when that button is pressed it passes parameters from the UDT to a popup window and opens said popup window at the mouse cursor location.

I tested the below script with just a normal button on a screen and it works, but when I try to do it with a templates button the window does shift over some in the right direction, but not to the mouse cursor. I assume this has something to do with the button being inside of the template container instead of the root container?

mouseX = event.x
mouseY = event.y
compX = event.source.getX()
compY = event.source.getY()
parWindow = system.gui.getParentWindow(event)
windowX = parWindow.getX()
windowY = parWindow.getY()
param1 = event.source.parent.MotorNumber

window = system.nav.openWindow('Popup Windows/PRP_Motor_FVNR', {'MotorNumber' : param1})

window.setLocation(mouseX+compX+windowX,mouseY+compY+windowY)

Correct, the x & y of the event are relative to the component of the event. To obtain the placement on the screen, you’ll need to traverse the chain of parents of the component, adding their offsets. You are missing the position of the template within the window.

SwingUtilities may be helpful here:
https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/swing/SwingUtilities.html#convertPointFromScreen(java.awt.Point,java.awt.Component)
https://docs.oracle.com/en/java/javase/11/docs/api/java.desktop/javax/swing/SwingUtilities.html#convertPointToScreen(java.awt.Point,java.awt.Component)

1 Like

Thanks both of you! I’d been brute forcing it from some forum posts and what I thought would work - but the SwingUtilities documents will be helpful

So I was able to find another forum post trying to solve a similar problem and using the convert point to screen swingutility - the script functions. However, the script fails if I have a second vision window open on another monitor. It will only function for the screen that is located at the top-left monitor position. For multi-monitor it fails and trys to open the pop-up offscreen. Any advice?


def setRelativeLocation(event, window, compRelX, compRelY):
	windowX = window.getX()
	windowY = window.getY()
	
	screenRelX, screenRelY = system.gui.convertPointToScreen(compRelX, compRelY, event)

	window.setLocation(screenRelX, screenRelY)


param1 = event.source.parent.MotorNumber

win = system.nav.openWindow('Popup Windows/PRP_Motor_FVNR', {'MotorNumber' : param1})
setRelativeLocation(event, win, event.x, event.y)


You don’t want screen coordinates. You want coordinates within the frame containing the parent window. Consider experimenting with the more generic convertPoint() method, where source is your template and dest is your parent window’s parent.

1 Like

For posterity.. (i.e. for future me), you can use this:

from javax.swing import SwingUtilities
window = system.nav.openWindow('Popup Path', {})
newPoint = SwingUtilities.convertPoint(event.source, event.x, event.y, system.gui.getParentWindow(event).rootContainer)
window.setLocation(newPoint.x, newPoint.y)

Thanks Phil for the massive prompt

3 Likes

For posterity:
https://docs.inductiveautomation.com/display/DOC81/system.gui.convertPointToScreen

Pointtoscreen isn't helpful in most cases though. I tried it with my 3 monitors and my new point was off the page :frowning: it also doesn't help for clients that are not fullscreen if displayed on a single monitor system, since the point still references the top left of the monitor, not the client

2 Likes

You and Phil are the men! I tried using PointToScreen and it broke bc of multiple monitors - this worked excellently!

I implemented something similar to this with

from javax.swing import SwingUtilities
from com.inductiveautomation.factorypmi.application import VisionDesktop
appWindow = SwingUtilities.getAncestorOfClass(VisionDesktop, event.source)
window.setLocation(SwingUtilities.convertPoint(event.source, event.x, event.y, appWindow))

Seems to work well enough, but wondering if I should change it to what is shown here.