JNA Java - Callback only work when there is no Jframe - java

I've programmed a DLL in C. The first function sends a pointer of the callback function that is called when new data is available.
So I use JNA to wrap this function.
In order to avoid the end of the app, I use an InputStreamReader that wait data from the standard input. And when new data are available the callback is called and data are printed in the console.
But, if I use a JFrame to avoid the end of the program before closing the window, it doesn’t work properly. In fact, if I don’t resize the JFrame window, the callback is called about 30 times and after that nothing (even if new data are available). If I resize the window, the callback if never called (even if new data are available).
Please could you help me?
Thanks
Edit : This is my main method.
package jsigmausblib;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import javax.swing.JFrame;
public class JSigmaUSBLib {
public static void main(String[] args) {
NativeSigmaUSBLibInterface nsuli = (NativeSigmaUSBLibInterface) Native.loadLibrary("SigmaUSBLib1.0", NativeSigmaUSBLibInterface.class);
ReadCallback rc = new ReadCallback() {
#Override
public void callbackFunction(Pointer readData, byte len) {
System.out.println("ok"+readData.getByte(0));
}
};
SigmaUSBLibConfigStruct.ByValue config = new SigmaUSBLibConfigStruct.ByValue();
nsuli.SigmaUSBLibInit(rc , config);
JFrame frame = new JFrame("Debug");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(80, 60);
frame.setVisible(true);
}
}

Related

Java frame.dispose(); not working

Can anyone guide me on why 'frame.dispose();' doesn't dispose the frame? The other method is called but 'frame.dispose();' is just ignored. This java class is used to check whether a stored answer that is made from another java class (RecoveryQuestion.check()) is the same as the user's input. Public variables such as StoredQuestion and StoredPassword are in the RecoveryQuestion class as well. Furthermore, I'm using Intelli J IDEA GUI form and I don't know how to extract the code, however, the form runs smoothly as intended except with the frame.dispose();
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.io.IOException;
public class ForgotPassword {
private JPanel panel1;
private JTextField answer;
private JLabel Question;
private JButton Submit;
private JFrame frame = new JFrame("Password Reset");
public ForgotPassword() {
Submit.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(RecoveryQuestion.StoredPassword.equals(answer.getText())) {
//frame.dispatchEvent(new WindowEvent(frame, WindowEvent.WINDOW_CLOSING));
frame.dispose();
FirstRun.main(null);
}
else JOptionPane.showMessageDialog(null,"Incorrect Answer");
}
});
}
public void setUI() {
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setContentPane(new ForgotPassword().panel1);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.setPreferredSize(new Dimension(400,250));
frame.pack();
frame.setResizable(false);
}
public static void main(String[] args) {
try{
RecoveryQuestion.Check();
} catch(IOException e1) {}
new ForgotPassword().setUI();
}
private void createUIComponents() {
// TODO: place custom component creation code here
Question = new JLabel();
Question.setText(RecoveryQuestion.StoredQuestion);
}
}
Every call to new ForgotPassword() does just that -- it creates a completely new and unique ForgotPassword instance. Look at your code above, and count how many times that you call this -- I see two times, suggesting that your problem is that you're displaying a JFrame from one of these instances, and trying to dispose of it in another -- two different JFrames that are unrelated to each other.
Suggestions:
Your code is very convoluted with instances creating instances of them self within their self. Simplify.
Create only one ForgotPassword in your GUI and pass it where needed
Side issue: shouldn't this sort of window be a dialog window (i.e., a JDialog) and not an application window (i.e., a JFrame)?
If your code did work as intended, then calling .dispose() on this JFrame should cause the JVM to exit (the entire program to end) since you're setting its default close operation to EXIT_ON_CLOSE.
Side issue 2: your posted code is not a valid MCVE meaning we cannot easily copy the code, paste it into our IDE and compile and run it without modification, making it more difficult for us to fully understand your code and forcing me to guess at your problem. In the future (and now), please consider posting one of these. Note that we do not want to see your entire program, nor should you post a link to a code repository. Instead keep it small, keep it simple, and make it functioning.

Show a simple message box in Pentaho

I am moving from SSIS to Pentaho, also new in java. What I would like to do is to show a simple message box in Pentaho using the Defined Java Class step (or another one).
First I tried with this code:
import javax.swing.JOptionPane;
public class MyClass
{
public static void main(String args[]){
JOptionPane.showMessageDialog(null,"Hello, this message is in a message type box." );
System.exit(0);
}
}
But I got this error:
Non-abstract class "Processor" must implement method "boolean org.pentaho.di.trans.steps.userdefinedjavaclass.TransformClassBase.processRow
I modified the code:
import javax.swing.JOptionPane;
public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException
{
JOptionPane.showMessageDialog(null,"Hello world!");
System.exit(0);
return true;
}
I tested the class, I did not receive any error message, but I could not see the message box that I was expecting.
So, my question is, what else do I need to import, specify or modify in order to achieve what I want to do.
Regards.
In pdi transformations most steps require some input. Your processRow() method is called for each row, received by your User Defined Java Class step. So, if you don't have input row - the method is not called.
You may want to place some step, producing one row before and pass the output to the java step. You may use "Detect empty stream" step - it will output exactly one row without any columns. However, your java code would still require some adjustments (not sure what exactly you need to do it in java, but it seems, like you need to create some ).
So, the easiest option for you would be to use "Modified Java Script Value" (it uses Rhino javascript, not java) step and call Alert("Hello world!") function inside. But nevertheless you would still need an input row.
If you still want to do it java way, you may try following code (but I am not a java developer, so I am not sure how good that code is):
import javax.swing.*;
public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException
{
Object[] r = getRow();
if (r == null) {
setOutputDone();
return false;
}
if (first)
{
first = false;
myFrame = new MyFrame();
// myFrame.setVisible(true);
JOptionPane.showMessageDialog(myFrame, "Hello world");
myFrame.dispose();
}
return true;
}
private MyFrame myFrame;
private class MyFrame extends JFrame {
public MyFrame() {
super();
// this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Also, please keep in mind, that kettle jobs/transformations usually are not supposed to be interactive. They may be executed on linux systems, which may have no windowing system.
So displaying such messages is usually used only for debugging and is disabled in production versions.

Local variable not used [JAVA]

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MyCalculatorGUI extends JFrame implements ActionListener {
JButton tripled, doubled;
JTextField input, output;
JPanel p1, p2;
MyCalculatorGUI() {
Container c = getContentPane();
tripled = new JButton("Triple");
tripled.addActionListener(this);
doubled = new JButton("Doubled");
doubled.addActionListener(this);
input = new JTextField("Input a number here.");
output = new JTextField("Result..");
p1.add(doubled);
p1.add(tripled);
p2.add(input);
p2.add(output);
c.add(p1);
c.add(p2);
setVisible(true);
setSize(400,400);
}
public void actionListener(ActionEvent e) {
}
public static void main(String[] args) {
MyCalculatorGUI output = new MyCalculatorGUI();
}
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
}
}
Eclipse is having a problem with my code where it is MyCalculatorGUI, it says the local variable is not used. Can somebody help me fix this?? I have recently just moved to Eclipse and everything I have tried to fix this isn't working for me.
I think you have created an object and not using it anywhere in main method
MyCalculatorGUI output = new MyCalculatorGUI();
This is just a warning by Eclipse. It cannot see that your actual logic happens inside the constructor - so it thinks you create a new object of your class MyCalculatorGUI inside the main method, but never use it. This could be a sign for unnecessary memory usage/consumption which might be a problem in large projects...
IF you change the line to just new MyCalculatorGUI(); the warning will disappear.
This is not an error, it's just a warning.
It simply means that you have created a variable which is never accessed later in the code. If you don't need it, then don't create it. If you do then just make use of it ;)
MyCalculatorGUI output = new MyCalculatorGUI(); //either delete this line
output.someMethod(); //or use the instance in some way
The warning should dissapear afterwards.
You don't use the variable you created in the main method, so either don't create it, use it or add the following above the main method: #SuppressWarnings("unused")
It's not a problem, it's just an Eclipse information to inform you that your local variable is not used. You can compile with 0 problem!
To resolve the warning you have two solutions:
First:
Implement the variable:
MyCalculatorGUI myCalculator = new MyCalculatorGUI();
Second:
Use the SupressWarnings on the top of your function like that:
#SuppressWarnings("unused")
MyCalculatorGUI() {
Container c = getContentPane();
tripled = new JButton("Triple");
tripled.addActionListener(this);
doubled = new JButton("Doubled");
doubled.addActionListener(this);
input = new JTextField("Input a number here.");
output = new JTextField("Result..");
p1.add(doubled);
p1.add(tripled);
p2.add(input);
p2.add(output);
c.add(p1);
c.add(p2);
setVisible(true);
setSize(400,400);
}

How to detect keypress

I am using java and trying to write a simple sudo mouse recorder that will store the mouse position when the space key is pressed. The only key I need to detect is the space key (Although if another key is easier, that will work).
I need the whole mouse recorder to be written in java, but it is OK if the function for the keypress is in another language. And I will be runing this in Windows 7.
What is the simplest way to do what has been described? All of the methods I have found require at minimum 20 lines of code. This is OK, except I don't understand how to implement them. I have an example source below:
import java.awt.MouseInfo;
import javax.swing.JOptionPane;
public class MouseRecorder {
public static void main (String[] args)
{
int slot = 0;
int xLoc[10];
int yLoc[10];
while (slot <= 10)
{
if (keyPressed(KEY_SPACE)) //<<<<This obviously won't work, but I'm looking for the simplest way to code this
{
xLoc[slot] = MouseInfo.getPointerInfo().getLocation().x;
yLoc[slot] = MouseInfo.getPointerInfo().getLocation().y;
slot++;
}
}
//The mouse information can now be utilized
}
}
Again your question is not clear since you have not addressed my comment:
It smells like to me that you might want a system-wide key logger that only responds to one key press, and that doesn't need a GUI. If this is so, then your best solution is to not use Java to create your application but to use a tool that can get closer to the OS. AutoIt comes to mind if this is for a Windows project. Please define your needs better.
and this forces us to guess at the problem and its solution.
If you are interested in creating a Swing GUI, having it take focus, and have it listen to key events, then the solution is to do this:
Create your Swing GUI and display it, leaving it as the active windowed application while your application is running.
Using Key Bindings have it listen for space bar presses
And then log the mouse location when the space bar is pressed.
As noted, this will not be achievable in 5 lines of code, so put that idea to the side.
If on the other hand your desire is to not have a GUI but rather listen for hot-key presses while any and all applications are running, then
The possible platforms used will be critical since your solution will require OS-specific code since creating a hot-key means having to create a keyboard handler routine, often in C, and doing this for each platform, and then linking it in to Java using JNI or JNA.
Or as noted another way is to link your Java program with an OS specific utility program or script such as AutoIt.
If you need more specific help, then please clarify your question.
Edit
You state:
Thank you for the answer, but as I have described above: "Changing languages is out of the question although it seems like that might be easier." and "I dont want a gui, if I can avoid it"
Then my second answer is what you're looking for. How adept are you at C/C++, JNI or JNA, and how good is your knowledge of operating system libraries? If you want a Java only solution, I would consider your requirements far above beginner or intermediate Java and into the realm of advanced -- or at least beyond my abilities at the moment, although I am sure that I could come up with some solutions after several days to a week or two of study.
... or consider getting rid of your "changing languages" requirement and instead allow at least meshing Java together with a scripting utility, like AutoIt. That could allow creation of solutions in a shorter period of time, at least for me. A limitation though is that these would be platform specific solutions. What is your purpose behind all of this? Could this be an XY problem in disguise?
Edit 2
I decided to try to solve this with a small AutoIt utility that I meshed with Java, and this is what I came up with.
My AutoIt program is called CaptureHotKey.au3, and it is compiled to an exe before use:
$key = $CmdLine[1]
HotKeySet($key, "hotKeyFunction")
While 1
Sleep(100)
WEnd
Func hotKeyFunction()
ConsoleWrite(#CRLF)
EndFunc
There's not much to it. All it does is set a hot-key from the first command line parameter, provides an endless while loop so that it will continue to run, and a hotkey function that is quite simple and only sends a carriage-return/line-feed to the console (which will be the standard output).
Then a Java class to help interact with this. It uses SwingPropertyLanguageSupport to allow addition of PropertyChangeListeners that respond on the Swing thread (in case I want to use this with a GUI).
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import javax.swing.event.SwingPropertyChangeSupport;
public class CaptureHotKey implements Runnable {
public static final String HOT_KEY = "hot key";
private String hotKey;
private SwingPropertyChangeSupport pcSupport = new SwingPropertyChangeSupport(
this);
private Scanner scanner;
private CaptureHotKeyFromAutoIt capture;
public CaptureHotKey(final String hotKey) throws IOException {
this.hotKey = hotKey;
capture = new CaptureHotKeyFromAutoIt(hotKey);
scanner = new Scanner(capture.getReadable());
}
public void startCapturing() {
new Thread(this).start();
}
public void exit() {
if (capture != null) {
capture.exit();
}
if (scanner != null) {
scanner.close();
}
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcSupport.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcSupport.removePropertyChangeListener(listener);
}
public String getHotKey() {
return hotKey;
}
#Override
public void run() {
while (scanner != null && scanner.hasNextLine()) {
scanner.nextLine();
pcSupport.firePropertyChange(HOT_KEY, true, false);
}
}
private static class CaptureHotKeyFromAutoIt {
public static final String AUTO_IT_APP_PATH = "CaptureHotKey.exe";
private Process process = null;
private ProcessBuilder pb;
public CaptureHotKeyFromAutoIt(String hotKey) throws IOException {
List<String> cmdList = new ArrayList<>();
cmdList.add(AUTO_IT_APP_PATH);
cmdList.add(hotKey);
pb = new ProcessBuilder(cmdList);
pb.redirectErrorStream(true);
process = pb.start();
}
public void exit() {
if (process != null) {
process.destroy();
}
}
public Readable getReadable() {
if (process != null) {
return new InputStreamReader(process.getInputStream());
}
return null;
}
}
}
Finally a Java class to test this set up:;
This adds a PropertyChangeListener to the class above to allow it to be notified if the hot-key is pressed:
import java.awt.MouseInfo;
import java.awt.PointerInfo;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.Scanner;
public class CaptureHotKeyTest {
public static final String CTRL_R = "^r"; // "{SPACE}" works for spacebar
private static final String EXIT = "exit";
private CaptureHotKey capture;
public CaptureHotKeyTest() {
try {
capture = new CaptureHotKey(CTRL_R);
capture.addPropertyChangeListener(new HotKeyPropertyChngListener());
capture.startCapturing();
Scanner scan = new Scanner(System.in);
System.out.println("Press control-r to get mouse position.");
System.out.println("Type \"exit\" to exit program");
while (scan.hasNextLine()) {
String line = scan.nextLine();
if (line.equalsIgnoreCase(EXIT)) {
scan.close();
capture.exit();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private class HotKeyPropertyChngListener implements PropertyChangeListener {
#Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(CaptureHotKey.HOT_KEY)) {
System.out.println("hot key pressed");
PointerInfo pointerInfo = MouseInfo.getPointerInfo();
System.out.println("Mouse: " + pointerInfo.getLocation());
}
}
}
public static void main(String[] args) {
new CaptureHotKeyTest();
}
}
You should use KeyListener: http://docs.oracle.com/javase/tutorial/uiswing/events/keylistener.html
It works fine with Swing

Application Wrapper using Java

Is it possible to implement a wrapper application for other (Java) applications using Java?
The purpose is to enforce usage policies for documents independent of the application used to work with a specific document.
E.G. I have an encrypted file that needs to be decrypted and opened in some kind of editor. So the wrapper application would decrypt the file and start the editor within itself to enforce an read-only policy by denying the write-access to the application, for example. Therefore the Runtime.getRuntime().exec(<command>) method doesn't fit well :)
There are also some ways to intercept method invocations within the same application but none that would wrap a whole other application.
I've also read about altering the JVM itself to intercept the file access. That sounds pretty good. But I need to dynamically change the policy depending on a user. That might not work as far as I know by now.
I guess there might not be any way to do this using Java code, but I'd appreciate any kind of hints and help.
I've also read about altering the JVM itself to intercept the file access. That sounds pretty good. But i need to dynamically change the policy depending on a user.
Set a custom SecurityManager that overrides checkWrite(String) to throw an exception.
Here is a simple example that prevents child frames from exiting the VM (checkExit(int)).
import java.awt.GridLayout;
import java.awt.event.*;
import java.security.Permission;
import javax.swing.*;
/** NoExit demonstrates how to prevent 'child' applications from
* ending the VM with a call to System.exit(0). */
public class NoExit extends JFrame implements ActionListener {
JButton frameLaunch = new JButton("Frame");
JButton exitLaunch = new JButton("Exit");
/** Stores a reference to the original security manager. */
ExitManager sm;
public NoExit() {
super("Launcher Application");
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
sm = new ExitManager( System.getSecurityManager() );
System.setSecurityManager(sm);
setLayout(new GridLayout(0,1));
frameLaunch.addActionListener(this);
exitLaunch.addActionListener(this);
add( frameLaunch );
add( exitLaunch );
pack();
setSize( getPreferredSize() );
setLocationByPlatform(true);
}
public void actionPerformed(ActionEvent ae) {
if ( ae.getSource()==frameLaunch ) {
TargetFrame tf = new TargetFrame();
} else {
// change back to the standard SM that allows exit.
System.setSecurityManager(
sm.getOriginalSecurityManager() );
// exit the VM when *we* want
System.exit(0);
}
}
public static void main(String[] args) {
NoExit ne = new NoExit();
ne.setVisible(true);
}
}
/** Our custom ExitManager does not allow the VM to exit, but does
* allow itself to be replaced by the original security manager. */
class ExitManager extends SecurityManager {
SecurityManager original;
ExitManager(SecurityManager original) {
this.original = original;
}
/** Deny permission to exit the VM. */
public void checkExit(int status) {
throw( new SecurityException() );
}
/** Allow this security manager to be replaced,
if fact, allow pretty much everything. */
public void checkPermission(Permission perm) {
}
public SecurityManager getOriginalSecurityManager() {
return original;
}
}
/** This example frame attempts to System.exit(0) on closing, we must
* prevent it from doing so. */
class TargetFrame extends JFrame {
TargetFrame() {
super("Close Me!");
add(new JLabel("Hi!"));
addWindowListener( new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.out.println("Bye!");
System.exit(0);
}
});
pack();
setSize( getPreferredSize() );
setLocationByPlatform(true);
setVisible(true);
}
}
The Eclipse RPC may be a good option to look at. It provides editor views which can easily be changed to enable / disable save, and other functionality at run time. Since Eclipse is written in Java, most Java code you already have will play nice with the framework.

Categories

Resources