Avoid tooltip grabbing mouse focus - java

How can I spawn a tooltip close to my cursor without the OnMouseExit handler being called. Is there any way to make the tooltip opaque to mouse focus?
A JIRA issue was created several years ago describing a similar situation: https://bugs.openjdk.java.net/browse/JDK-8118199 .
Working with a canvas I attached mouse listener to continuously show a tooltip and update accordingly to the data drawn beneath it.
Tooltip tt = new Tooltip();
tt.setAnchorLocation(AnchorLocation.CONTENT_BOTTOM_RIGHT);
tt.setAutoFix(false);
double offset = 100;
this.setOnMouseMoved((event) -> {
//Position tooltip
if (!tt.isShowing()) {
tt.show(this, event.getScreenX() - offset, event.getScreenY() - offset);
} else {
tt.setX(event.getScreenX() - offset);
tt.setY(event.getScreenY() - offset);
}
//Update text
int xBucket = (int) ((event.getX() - marginLeft - gridXOffset) / (gridWidth / xSections));
int yBucket = (int) ((event.getY() - marginTop) / (gridHeight / ySections));
DoubleSummaryStatistics stat = dat[xBucket][yBucket];
tt.setText("Occurances: " + stat.getCount() + "\n"
+ "Average Fitness: " + df.format(stat.getAverage()) + "\n"
+ "Max Fitness: " + df.format(stat.getMax()) + "\n"
+ "Min Fitness: " + df.format(stat.getMin()));
});
this.setOnMouseExited((event) -> {
if (tt.isShowing()) {
tt.hide();
}
});
As you can see the tooltip is displayed a little bit to the top left due to the defined offset. If the value is set two a smaller value (20-0) the tooltip will grab the focus as soon as it is displayed and the setOnMouseExit handler will be immediately called resulting in a flickering loop.

Related

Default button with JOptionsPane not working properly

I posted this code yesterday for another issue but now I once again must call on you all for help.. I appreciate all the assistance so far I have had without this community I wouldn't have made it so far.
Now, my problem is quite simple. I have a GUI with an input box for the user and three buttons. The buttons are not JButtons, they are the standard JOptionsPane yes, no, and cancel buttons. I did change the text to "next entry", "next batch", and "finished".
Before I made changes to my GUI I had standard buttons. The button that will most often be used is the "yes" button (now "next entry").. This button will be clicked a LOT in my program. Before the default button setting worked.. A user could simply type a number and press enter quickly. Now the enter key will not activate the default button instead the user must physically click on it.. This is what I want to change.
Is there any way I can set the below code so when the user clicks enter, regardless of what text they have typed, the "yes" (now "next batch" is clicked on default)? For what it's worth I did do research on this but could not find a solution that suited my specific circumstances.
package nacha;
import java.awt.BorderLayout;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class Testing4
{
public static void main(String args[]){
String css = "<span style='font-size:10; color: white; background-color:black'>";
String batchCss = "<span style='font-size: 20'>";
String endSpanCss = "</span>";
String table = "<table border=4>";
String endTable = "</table>";
String mainCss = "<span style='font-size:12; color: red'>";
String header1Css = "<span style = 'font-size:15; font-weight:bold;text-decoration:underline;border:1px dotted red'>";
String text1Css = "<span style = 'font-size:12; font-style:italic'>";
String text = "<html>" +
css + batchCss + "1 of 2"+endSpanCss+endSpanCss+ endSpanCss +
"<br><br><br>"+header1Css+"Entry Detail:"+endSpanCss +
"<br>"+mainCss+"111111111111111111111"+endSpanCss+
"<br><br><br>"+text1Css+"Please type 1-21 to apply a reason code and addenda record to the entry detail." +
"<br>Please type 'h' and press the next entry button to open the help screen."+endSpanCss +
"<br><br><br>"+header1Css+"Reason Codes"+ endSpanCss +
"<br>"+table+"R01 - Insufficient Funds" +
"<br>R02 - Account Closed" +
"<br>R03 - No Account" +
"<br>R04 - Invalid Account Number" +
"<br>R05 - Unauthorized Debit to Consumer Account" +
"<br>R06 - Returned per ODFI Request" +
"<br>R07 - Auth Revoked by Customer" +
"<br>R08 - Payment Stopped" +
"<br>R09 - Uncollected Funds" +
"<br>R10 - Customer Advises Not Authorized" +
"<br>R11 - Check Truncation Entry Return" +
"<br>R12 - Branch Sold to Another DFI" +
"<br>R13 - Invalid ACH Routing Number" +
"<br>R14 - Represenative Payee Deceased or Unable to Continue" +
"<br>R15 - Beneficiary or Account Holder Deceased" +
"<br>R16 - Account Frozen" +
"<br>R17 - File Record Edit Criteria" +
"<br>R18 - Improper Effective Entry Date" +
"<br>R19 - Account Field Error" +
"<br>R20 - Non-Transaction Amount" +
"<br>R21 - Invalid Company Information" +
"<br>R22 - Invalid Individual ID Number"+endTable;
//Below code creates the GUI for the return builder portion of the program.
Object[] options1 = {"Next Entry","Next Batch","Finished"};//Changes the default buttons.
BorderLayout border = new BorderLayout();
JPanel panel = new JPanel();
panel.setLayout(border);
panel.add(new JLabel(text),BorderLayout.NORTH);//Adds the label to the top of the panel.
JTextField textField = new JTextField(10);
panel.add(textField,BorderLayout.SOUTH);//Adds a user-input text area to the bottom of the panel.
int result = JOptionPane.showOptionDialog(null, panel, "Return Builder", JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, options1, JOptionPane.YES_OPTION);
}
}
You need to pass the default option as the final argument to JOptionPane.showOptionDialog:
int result = JOptionPane.showOptionDialog(null, panel, "Return Builder",
JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null,
options1, options1[0]);
This will have the side effect of making that button have the initial keyboard focus whenever the dialog is displayed. If you don't want that, you can force the JTextField to receive the focus whenever it is displayed in a window:
textField.addHierarchyListener(new HierarchyListener() {
#Override
public void hierarchyChanged(HierarchyEvent e) {
final Component c = e.getComponent();
long flags = e.getChangeFlags();
if ((flags & HierarchyEvent.SHOWING_CHANGED) != 0 &&
c.isShowing()) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
c.requestFocusInWindow();
}
});
}
}
});
A side note: For asking the user to select from a list of known options, a JComboBox is a better choice than a JTextField. Your Help option can simply be a different JButton, present in the message body of the JOptionPane.

java PrintService, missing MediaSize in getSupportedAttributeValues

In the settings of the printer I made a new Format named custom1 with width 57 and height 100. Also I changed the custom format to the same width and height.
With the following routine I tried to figure out the supported mediasizes:
Media[] res = (Media[])printService.getSupportedAttributeValues(Media.class, null, null);
for (Media media : res) {
if (media instanceof MediaSizeName) {
MediaSizeName msn = (MediaSizeName) media;
MediaSize ms = MediaSize.getMediaSizeForName(msn);
float width = ms.getX(MediaSize.MM);
float height = ms.getY(MediaSize.MM);
System.out.println("Class:" + msn.getClass().getName()
+ "; toString:" + msn.toString() + "; width:"
+ width + "; height:" + height);
}
}
But in the list is neither custom nor custom1. Also about the half number of the formats are missing in the list.
What is the problem? Does this printer not support the MediaSizes in Java?
What can I do?
When I test this on another printer the custom MediaSize with the right width and height is supported. Where is the problem with this printer?
Thanks for all answers

calling a second method while one method call is still in progress causes program to crash

I am having some trouble with a couple of methods in my program: I have a method that is called when the user clicks a start button on the GUI. This method will receive all of the network traffic currently being sent/ received over the network, and display information about it to the user. The user can stop this method being called by clicking the stop button.
This method currently looks like this:
public static void retrieveFilteredPdu(){
/*Try/Catch block copied from 'receivePdu()' method in EspduReceiver.java on 07/05/2014
* Now edit it so that it will receive all PDUs, but only display the ones matching the filter values in the top JTextArea */
try{
/*Specify the socket to receive the data */
EspduReceiver.socket = new MulticastSocket(EspduSender.PORT);
EspduReceiver.address = InetAddress.getByName(EspduSender.DEFAULT_MULTICAST_GROUP);
EspduReceiver.socket.joinGroup(EspduReceiver.address);
//stopCapture = false;
/*Loop infinitely, receiving datagrams */
while(true){
/*First, set the value of the 'stopCapture' boolean to 'false', in case it has previously been set to true during the life of
* the program */
/*stopCapture = false; /*For some reason, if I do this here, clicking the 'Get site' button causes the program to start receiving
PDUs again, and you are not able to stop it without manually shutting down the program. Possibly because I am infinitely
setting the value of 'stopCapture' to false?*/
byte buffer[] = new byte[EspduReceiver.MAX_PDU_SIZE];
EspduReceiver.packet = new DatagramPacket(buffer, buffer.length);
EspduReceiver.socket.receive(EspduReceiver.packet);
Pdu pdu = EspduReceiver.pduFactory.createPdu(EspduReceiver.packet.getData()); /*Moved this line to the top of the class to declare as global variable (29/04/2014) */
if(pdu != null){
System.out.print("Got PDU of type: " + pdu.getClass().getName());
if(pdu instanceof EntityStatePdu){
EntityID eid = ((EntityStatePdu)pdu).getEntityID();
Vector3Double position = ((EntityStatePdu)pdu).getEntityLocation();
System.out.println(" EID:[" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
System.out.println("Location in DIS coordinates: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "] ");
/*Add PDU to ArrayList of PDUs */
EspduReceiver.espdu.add(pdu);
/* System.out.println(" PDU added to arrayList. ");
System.out.println(espdu); /*This is printing out the actual DIS messages (i.e. edu.nps.moves.dis.EntityState...),
maybe try adding the 'eid.getSite()', etc to an ArrayList instead. Use Associative arrays/ map/ hashmap */
EspduReceiver.entitySite.add(eid.getSite());
System.out.println("Entity Site added to ArrayList from Filter.retrieveFilteredPdu() ");
EspduReceiver.entityApplication.add(eid.getApplication());
System.out.println("Entity Application added to ArrayLIst. ");
EspduReceiver.entity.add(eid.getEntity());
System.out.println("Entity ID added to ArrayList");
/*Check that everything is actually in the ArrayLists
for(int i : entity){ /*Substituted 'entity' with 'entitySite' and 'entityApplication'- values are all printed correctly.
System.out.println(i);
} */
/*07/05/2014
* Write a method that will only append the PDUs that match the filter values to the text area,
* call that method here. */
/*Now append each PDU to the text area */
Gui.displayFilteredOutput.append("\n");
Gui.displayFilteredOutput.append("EID: [" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "]. ");
Gui.displayFilteredOutput.append("Location in DIS coordinates: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "] ");
/*Append every PDU that matches the filter criteria to the displayFilteredOutput JTextArea
Gui.displayFilteredOutput.append("\n");
Gui.displayFilteredOutput.append("EID: [" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "]. ");
Gui.displayFilteredOutput.append("Location in DIS coordinates: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "] "); */
} else if(!(pdu instanceof EntityStatePdu)){
System.out.println("There are no PDUs currently being received.");
}
System.out.println();
}
Thread.sleep(1000);
/*Try adding a boolean to allow me to stop the capture by clicking 'stop' button- Look on stackoverflow */
boolean queryStopCapture = EspduReceiver.stopCapture;
if(queryStopCapture == true){
System.out.println("Break clause in 'queryStopCapture' if statement in EspduReceiver.java has been called. ");
break; /*Use a call to receivePdu() to populate the second JTextArea, but don't let it call a 'break' clause at all.
* Find some other way of adding a 'break' to the output displayed in the first JTextArea (01/05/2014)
* Maybe add this code to receivePdu() call in ActionListener instead of here.
*/
}
} /*end while */
} /*end try */
catch(Exception e){
System.out.println(e);
e.printStackTrace();
System.out.println("Error in retrieveFilteredPdu() method. ");
/*09/04/2014 # 17:100
* If this exception gets called, presumably it either means that pdu is not an instance of EntityStatePdu, or
* that pdu does not actually hold a packet. */
}
}
I have another method, which, in theory, should display information about only the network traffic which has attributes matching some values set by the user. This method is called when the user clicks the 'Filter' button on the GUI. The method currently looks like this:
public static void filterPDUs(){
// if(EspduReceiver.startCapture == true){
/*If EspduReceiver.startCapture is true, then the program is already receiving PDUs, so now I need to set it to only display the ones that
* match the filter criteria. Do this by checking the PDU attributes against the filter values before printing- if they match, then print,
* if not, don't. */
if((EspduReceiver.startCapture == true) && (EspduReceiver.stopCapture == false)){
/*Get the size of the sitesToBeFiltered ArrayList, and store in a variable. Will need to update the variable with every iteration
* of the loop, because the ArrayList will keep growing as long as the capture is running. */
int sitesToBeFilteredSize = sitesToBeFiltered.size();
int matchingSitesIterator = 0;
/*First, check if site filter value matches the PDU's site, if it does, then check Application, if it matches again, then check ID.
* If at any point it doesn't match, exit the while loop. */
while(matchingSitesIterator < sitesToBeFilteredSize){
System.out.println("SitesToBeFiltered.size() = " + sitesToBeFilteredSize);
if(sitesToBeFiltered.get(matchingSitesIterator) == Filter.filter1Value){
if(applicationsToBeFiltered.get(matchingSitesIterator) == Filter.filter2Value){
if(IDsToBeFiltered.get(matchingSitesIterator) == Filter.filter3Value){
Gui.displayFilteredOutput.append("Matching PDU found: [" + sitesToBeFiltered.get(matchingSitesIterator) + ", " + applicationsToBeFiltered.get(matchingSitesIterator) + ", " + IDsToBeFiltered.get(matchingSitesIterator) + "] ");
} else {Gui.displayFilteredOutput.append("Sorry, there were no PDUs found with the specified ID value.");}
Gui.displayFilteredOutput.append("Need to display every PDU that had a matching Site & Application here. ");
}else {Gui.displayFilteredOutput.append("Sorry, there were no PDUs found with the specified Application value.");}
Gui.displayFilteredOutput.append("need to display every PDU that had a matching Site here. ");
}else {Gui.displayOutput.append("Sorry, there were no PDUs found with the specified Site value.");}
}
} else {
Gui.displayFilteredOutput.append("Do something if EspduReceiver.startCapture is not true, and EspduReceiver.stopCapture is not false");
}
// }else if(EspduReceiver.startCapture == false){
/*If EspduReceiver.startCapture is false, then the program is not receiving PDUs, so I now need to call the method that will receive PDUs,
* and display only the ones that match the filter criteria. */
// }
}
The problem I'm having is that for some reason, if the user clicks the 'Filter' button to display only the PDUs with matching filter criteria, after clicking 'Start' (to call the first method), then the program crashes completely... (i.e. it appears to stop performing the function that it was carrying out, and will not respond to clicks on any buttons or even the 'Close window' button)
If they click 'Filter' after having clicked 'Start' & 'Stop' (i.e. when the first method is not running, then the second method performs its tasks as expected.
It seems that for some reason, calling the second method while the first method is still running causes the program to crash- and I can't work out why this is... can anyone point out what's going wrong here?
Edit
I have the following code in my main method:
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run(){
Gui gui = new Gui();
gui.setVisible(true);
}
});
}
You need to show more of the code, as others have said, but if you're using Swingworkers or other threads to run these methods, then either the methods have to be thread-safe or they need to be synchronized to prevent their execution from being interleaved. If you're directly accessing Swing components outside the event-dispatching thread, then Swing will make demons come out of your nose, so don't do that (there are some special exceptions for some text components, but generally it's prohibited). If you're not sure, stick assert java.awt.EventQueue.isDispatchThread() before every statement that constructs or uses a Swing object, and enable assertions in the runtime system.
I assume Gui is built on Swing. Read the Swing tutorial, and pay attention to the Event Dispatch Thread. I can't see how the Swing portion of you code works, but I'm guessing you are locking up the EDT somehow. A long-running process needs to run in its own thread and use SwingUtilities.invokeLater() to update Swing components, like your text area.

Collision if statement doesnt seem to work

Basically, Im just trying out a very simple collision test for another program Im working on, but it does seem to so simple (Or maybe Im just an idiot!) Anyway, here is the code:
public void run() {
while(true){
try {
if(rect.rect.intersects(rect1.rect)){
System.out.println("Test1");
if(rect1.x == ((rect.x + rect.width)-1)){
System.out.println("Test2");
rect1.x = rect.x + rect.width;
rect1.dx = 0;
}
}
rect.update();
rect1.update();
Thread.sleep(50);
The program does not get to test2!
Any help to solve this issue is greatly appreciated! Thanks in advance!
Paint component part:
public void paintComponent(Graphics g){
rect1.paint(g);
rect2.paint(g);
g.drawString(String.valueOf(rect1.x), 100, 100);
g.drawString(String.valueOf(rect2.x+rect2.width), 100, 150);
repaint();
}
Image:
Run the program in Eclipse (or your preferred IDE) and use its runtime debug facilities to set a breakpoint at the first if statement. Then step through and examine the values of the variables. Hopefully this will make clear why your code is failing to do what you expect.
How about constructing this method just for debugging convenience (unless you have a debugger):
public static printRectProperties(Rectangle rect, String rectangleName){
System.out.println(rectangleName + ": x = " + rect.x + ", y = "
+ rect.y + ", width = " rect.width + ", height = " + rect.height;
}
Then you can simply call this method to log statistics about the rectangles prior to the execution of the if statement:
if(rect.rect.intersects(rect1.rect)){
System.out.println("Test1");
printRectProperties(rect, "rect");
printRectProperties(rect1, "rect1");
if(rect1.x == ((rect.x + rect.width)-1)){
System.out.println("Test2");
That should make it easy to figure out why "Test2" is never printed.

Automatically opening pages on different monitors

I am designing an emergency response page, which needs to display information across 3 different monitors. The first monitor will gather information about the caller, and then contain 2 links. The first link needs to display a different web page on the 2nd monitor, and the 2nd link needs to display a different web page on the 3rd monitor.
Is this possible?
Thanks for any help
The first link needs to display a different web page on the 2nd monitor, and the 2nd link needs to display a different web page on the 3rd monitor.
While, depending on your operating system, it is possible to control where a window appears, there are much fewer options for doing this using javascript / serverside code over HTTP / browsers.
The only sensible way to achieve this is by configuring the displays to be tiles of a larger display rather than independent screens (for *nix/BSD/Linux, check out xinerama).
The code below saves the size of a window - and would only need some simple changes to support x/y offset and multiple windows - I leave it to you as to how you differentiate between the windows.
A simpler approach would be to just have one huge window with frames whose borders align with the monitors.
if (document.getElementById && !document.all) { // NOT for MSIE
stickySizeOverloadOnload(stickySizeSetWindowSize);
stickySizeOverloadOnresize(stickySizeSaveWindowSize);
}
function stickySizeSaveWindowSize(event)
{
var expiry = new Date();
var path = document.location.pathname;
expiry.setDate(expiry.getDate()+500);
stickySizeSetCookie('windowSize', window.outerWidth + ',' + window.outerHeight, expiry, path);
}
function stickySizeSetWindowSize()
{
var saved=stickySizeGetCookie('windowSize');
var parts=new Array();
if (saved.length) {
parts = saved.split(',');
if ((parts[0]>100) && (parts[1]>100)) {
window.outerWidth=parts[0];
window.outerHeight=parts[1];
} else {
alert("invalid size - '" + saved + "'");
stickySizeDeleteCookie('windowSize');
}
}
}
function stickySizeOverloadOnload(func)
{
var oldhandler=window.onload;
if (typeof window.onload != "function") {
window.onload=func;
} else {
window.onload=function(event) {
oldhandler(event);
func(event);
}
}
}
function stickySizeOverloadOnresize(func)
{
var oldhandler=window.onresize;
if (typeof window.onresize != "function") {
window.onresize=func;
} else {
window.onresize=function(event) {
oldhandler(event);
func(event);
}
}
}
function stickySizeSetCookie(name, value, expires, path, domain, secure) {
var curCookie = name + "=" + escape(value) +
((expires) ? "; expires=" + expires.toGMTString() : "") +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
((secure) ? "; secure" : "");
document.cookie = curCookie;
}
function stickySizeGetCookie(name) {
var dc = document.cookie;
var prefix = name + "=";
var begin = dc.indexOf("; " + prefix);
if (begin == -1) {
begin = dc.indexOf(prefix);
if (begin != 0) return null;
} else
begin += 2;
var end = document.cookie.indexOf(";", begin);
if (end == -1)
end = dc.length;
return unescape(dc.substring(begin + prefix.length, end));
}
function stickySizeDeleteCookie(name, path, domain) {
if (stickySizeGetCookie(name)) {
document.cookie = name + "=" +
((path) ? "; path=" + path : "") +
((domain) ? "; domain=" + domain : "") +
"; expires=Thu, 01-Jan-70 00:00:01 GMT";
}
}
You can open the links in a different window with the attribute target="windowName".
You have to set up the three windows manually, so assign them manually to the three screens. When you open a link again in a window it is still on the same screen.
Have a look at Java: Getting resolutions of one/all available monitors (instead of the whole desktop)?
(The answer discuss the GraphicsEnvironment.getLocalGraphicsEnvironment() call)
If you really want the windows to be locked to a specific monitor, you will need to implement this client side. Here is a link describing how to detect which monitor a window is on in Java, so you can move it to the proper monitor and maximize the window if you desire. Obviously you can implement the rest of the system server side and just display pages inside the windows you have created.

Categories

Resources