import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
public class clientWindow {
static Text chatWindow;
public static void sendMessage(Socket socket, String message) throws IOException {
PrintWriter pr = new PrintWriter(socket.getOutputStream());
pr.println("Client: " + message);
pr.flush();
}
public static void main(String[] args) throws UnknownHostException, IOException {
Socket s = new Socket("10.0.1.8", 4500);
Display display = new Display();
Shell clientWindow = new Shell(display);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
clientWindow.setLayout(layout);
GridData data = new GridData(GridData.FILL_HORIZONTAL);
GridData data1 = new GridData(GridData.FILL_BOTH);
chatWindow = new Text(clientWindow, SWT.MULTI | SWT.V_SCROLL | SWT.READ_ONLY);
chatWindow.setLayoutData(data1);
Text messageBox = new Text(clientWindow, SWT.SINGLE);
messageBox.setLayoutData(data);
Button send = new Button(clientWindow, 0);
send.setText("Send");
send.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent event) {
try {
sendMessage(s, messageBox.getText());
messageBox.setText("");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void widgetDefaultSelected(SelectionEvent arg0) {
// TODO Auto-generated method stub
}
});
clientWindow.open();
while (!clientWindow.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}
This is a small messaging app that I've finished. Everything in here works fine in Eclipse. When I try to run it in the Terminal, however, I get this.
Exception in thread "main" org.eclipse.swt.SWTException: Invalid thread access
at org.eclipse.swt.SWT.error(SWT.java:4711)
at org.eclipse.swt.SWT.error(SWT.java:4626)
at org.eclipse.swt.SWT.error(SWT.java:4597)
at org.eclipse.swt.widgets.Display.error(Display.java:1112)
at org.eclipse.swt.widgets.Display.createDisplay(Display.java:853)
at org.eclipse.swt.widgets.Display.create(Display.java:837)
at org.eclipse.swt.graphics.Device.<init>(Device.java:132)
at org.eclipse.swt.widgets.Display.<init>(Display.java:736)
at org.eclipse.swt.widgets.Display.<init>(Display.java:727)
at clientWindow.main(clientWindow.java:28)
I'm pretty sure this error happens when a trying to access the Display from something that isn't in "main", which isn't what I'm trying to do. So why is it giving me this error?
Judging by the line numbers in the Display code you are running this on macOS.
On macOS you must specify the -XstartOnFirstThread option when you run your code with the java command in Terminal.
The program works in Eclipse because Eclipse sets this up for you automatically in the Run Configuration.
Related
I've written an application to administer my audio files using Java/SWT. Now I want to copy files from the PC to my mobile Phone, which is a Samsung Galaxy A30, Android 10 device. When I hook up the phone to the PC (Win 10) it is listed in Explorer under "This PC" as "Galaxy A30s" and I can scroll through folders and files just fine. However when I open the SWT DirectoryDialog the phone is not listed there.
Has anybody a tip why this is and how to solve it?
Many thanks.
Here is the calling code snippet:
AudioFilesCopy afc = new AudioFilesCopy(shell);
if (afc.selectDirectory() != null) {
Cursor waitCursor = shell.getDisplay().getSystemCursor(SWT.CURSOR_WAIT);
shell.setCursor(waitCursor);
afc.copyFiles(plSongs);
shell.setCursor(null);
}
This is the class:
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Shell;
public class AudioFilesCopy {
private Shell shell;
private Logger logger;
private String selDirectory;
public AudioFilesCopy(Shell parent) {
logger = java.util.logging.Logger.getLogger(this.getClass().getName());
logger.addHandler(MusicCatalog.fileHandler);
shell = new Shell(parent, SWT.BORDER | SWT.RESIZE | SWT.Close | SWT.MAX | SWT.MIN | SWT.PRIMARY_MODAL);
shell.setLayout(new FillLayout());
}
public String selectDirectory() {
DirectoryDialog dialog = new DirectoryDialog(shell);
dialog.setFilterPath(System.getProperty("user.home") + "\\TransferOrdner");
selDirectory = dialog.open();
return selDirectory;
}
public void copyFiles(String[] plSongs) {
for (int i = 0; i < plSongs.length; i++) {
Path source = Paths.get(plSongs[i]);
Path target = Paths.get(selDirectory, source.getFileName().toString());
// System.out.println("Copy " + source + " to " + target);
try {
Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES);
} catch (IOException e) {
logger.log(Level.SEVERE, e.getMessage(), e);
}
}
}
}
Use FileDialog instead of DirectoryDialog.
I'd like to type: "/ammo" when I type ALT+A.
The program runs but it seems like to stop right after the running:
I press alt+A or A and the code is not doing anything at all.
package jnativehook01;
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyEvent;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;
public class Example implements NativeKeyListener {
public void nativeKeyPressed(NativeKeyEvent e) {
if (NativeKeyEvent.getKeyText(e.getKeyCode()).equals("A")) {
try {
GlobalScreen.unregisterNativeHook();
Robot bot;
try {
bot = new Robot();
String text = "/ammo";
StringSelection stringSelection = new StringSelection(text);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, stringSelection);
//type: /ammo
bot.keyPress(KeyEvent.VK_T);
bot.keyRelease(KeyEvent.VK_T);
} catch (AWTException e1) {
}
} catch (NativeHookException e1) {
}
}
}
public void nativeKeyReleased(NativeKeyEvent e) {
System.out.println("Key Released: " + NativeKeyEvent.getKeyText(e.getKeyCode()));
}
public void nativeKeyTyped(NativeKeyEvent e) {
System.out.println("Key Typed: " + e.getKeyText(e.getKeyCode()));
}
public static void main(String[] args) {
new Example();
}
}
Ok, now it's working:
package jnativehook01;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.keyboard.NativeKeyEvent;
import org.jnativehook.keyboard.NativeKeyListener;
import java.util.logging.*;
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyEvent;
import java.awt.event.InputEvent;
public class Example implements NativeKeyListener {
public void nativeKeyPressed(NativeKeyEvent e) {
if (NativeKeyEvent.getKeyText(e.getKeyCode()).equals("A")) {
Robot bot;
try {
String text = "/ammo";
StringSelection stringSelection = new StringSelection(text);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, stringSelection);
bot = new Robot();
for (int i = 0; i < 10; i++) {
//t
bot.keyPress(KeyEvent.VK_T);
bot.delay(100);
bot.keyRelease(KeyEvent.VK_T);
bot.delay(500);
bot.keyPress(KeyEvent.VK_CONTROL);
bot.keyPress(KeyEvent.VK_V);
bot.keyRelease(KeyEvent.VK_V);
bot.keyRelease(KeyEvent.VK_CONTROL);
bot.delay(500);
//Enter
bot.keyPress(KeyEvent.VK_ENTER);
bot.keyRelease(KeyEvent.VK_ENTER);
bot.delay(1000);
bot.keyPress(KeyEvent.VK_ENTER);
bot.keyRelease(KeyEvent.VK_ENTER);
bot.delay(400);
}
} catch (AWTException e1) {
}
}
}
public void nativeKeyReleased(NativeKeyEvent e) {
}
public void nativeKeyTyped(NativeKeyEvent e) {
}
public static void main(String[] args) {
Example ex = new Example();
try {
GlobalScreen.registerNativeHook();
Logger logger = Logger.getLogger(GlobalScreen.class.getPackage().getName());
logger.setLevel(Level.OFF);
} catch (NativeHookException eb) {
System.out.println(eb.getMessage());
}
GlobalScreen.addNativeKeyListener(ex);
}
}
There are still a few problems with your code.
if (NativeKeyEvent.getKeyText(e.getKeyCode()).equals("A")) {
This is not the correct way to check for the A key. This will check to see if AWT produces the ascii 'A' for that key. These values could be overridden by the JVM at runtime. You should check for the NativeKeyEvent.VK_A constant. You also fail to check for the ALT flag on that key event. Something like the following is more of what you are looking for.
if (e.getKeyCode() == NativeKeyEvent.VC_A && e.getModifiers() & NativeInputEvent.ALT_MASK) {
A note on thread safety. You are relying on AWT inside of the key callback, however, this library does not use AWT to dispatch events by default. You need to take a look at the Thread Safety section of the wiki for Thread Safe examples.
You may choose to replace the Robots class with GlobalScreen.postNativeEvent(...) for convenience, to omit Swing/AWT, but it is not required.
A note on blocking inside of the event listener callback. If you block inside this function, via sleep or other long running process, you may cause a delay in key event delivery by the OS or worse, library removal by some operating systems. This removal is outside the control of the library and controlled by the OS.
At present all my Java GUI applications have SWT.SWT as their window class. I would like for some of them to be linked as sub-windows in menu applications such as Cairo-Dock. This is the third column of the out put from wmctrl -lx.
I have tried using the Display.setAppName() method in an attempt to set this name. Neither Display.setAppName or display.SetAppname will change the app class from SWT.SWT to the class name I'm tring to set.
When I use the lower case display.setAppName it produces this warning in the Eclipse IDE:
Description Resource Path Location Type
The static method setAppName(String) from the type Display should be accessed in a static way WBTest.java /javaTools/src/javaTools line 31 Java Problem
Code Sample:
package javaTools;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.wb.swt.SWTResourceManager;
public class WBTest {
private Table table;
/**
* Launch the application.
* #param args
*/
public static void main(String[] args) {
try {
WBTest window = new WBTest();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display display = Display.getDefault();
display.setAppName("myapplication");
Shell shell = new Shell();
shell.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLACK));
shell.setSize(560, 426);
shell.setText("SWT Application");
table = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION);
table.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
// table.setBounds(49, 21, 241, 158);
table.setHeaderVisible(true);
table.setLinesVisible(true);
TableItem row = new TableItem(table, SWT.NONE);
row.setText("This is a test.");
shell.open();
// shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}
My research shows how to do this in Python, which works:
#!/usr/bin/python
from gi.repository import Gtk
win = Gtk.Window()
win.connect("delete-event", Gtk.main_quit)
win.set_wmclass ("Hello World", "Hello World")
win.set_title ("Hello World")
win.show_all()
Gtk.main()
I'm trying to do the same thing with SWT/Java.
Is there something else I need to add to this function to make it work, or is there a differernt function that is specific to setting the application's class name?
I don't know whether to remove this question or provide the answer. I had worked on it since yesterday and was still trying lots of variations.
One finally works. Apparently, the line has to appear in the code before declaring the Display.
This works:
package javaTools;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.wb.swt.SWTResourceManager;
public class WBTest {
private Table table;
/**
* Launch the application.
* #param args
*/
public static void main(String[] args) {
try {
WBTest window = new WBTest();
window.open();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Open the window.
*/
public void open() {
Display.setAppName("myapplication");
Display display = Display.getDefault();
Display.setAppName("myapplication");
Shell shell = new Shell();
shell.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLACK));
shell.setSize(560, 426);
shell.setText("SWT Application");
table = new Table(shell, SWT.BORDER | SWT.FULL_SELECTION);
table.setBackground(SWTResourceManager.getColor(SWT.COLOR_BLUE));
// table.setBounds(49, 21, 241, 158);
table.setHeaderVisible(true);
table.setLinesVisible(true);
TableItem row = new TableItem(table, SWT.NONE);
row.setText("This is a test.");
shell.open();
// shell.layout();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
}
I am currently working on an assignment in which I need to make an application that has two buttons: read/write, and a textArea with a gray background and blue text, that will display the read content of a file that is written to on button press. I have to save an array of 5 numbers, the date, and a double (2.5).
I have gotten to the point of getting everything to work except for the appending of the text to the textArea... no matter where I seem to pass the value it gives me an error or tells me that it doesn't exist as a variable!
My question is: How do I get the values that I have read from the file to update the text in the textArea instead of just console?
Here is my first file which will create the application and populate the scene. The buttons and text area are all the correct color.
package chapter17;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import java.io.IOException;
import javafx.scene.layout.Region;
import javafx.scene.control.TextArea;
import javafx.scene.control.Button;
import javafx.scene.layout.HBox;
public class Exercise17_5 extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primaryStage) {
HBox hBox = new HBox();
hBox.setSpacing(10);
hBox.setAlignment(Pos.CENTER);
Button write = new Button("Write");
Button read = new Button("Read");
TextArea readText = new TextArea("This is text testing...");
readText.setPrefColumnCount(15);
readText.setPrefRowCount(5);
readText.setWrapText(true);
readText.setStyle("-fx-text-fill: blue");
//readText.setStyle("-fx-background-color: grey");
readText.setFont(Font.font("Times", 20));
hBox.getChildren().addAll(write, read, readText);
ReadWrite readWriting = new ReadWrite();
write.setOnAction(e -> {
try {
readWriting.write();
}
catch (IOException excepiton) {
excepiton.printStackTrace();
}});
read.setOnAction(e -> {
try {
readWriting.read();
}
catch (IOException exception){
exception.printStackTrace();
}
});
Scene scene = new Scene(hBox,550,550);
primaryStage.setScene(scene);
primaryStage.setTitle("Exercise 17.5");
primaryStage.show();
Region region = (Region) readText.lookup(".content");
region.setStyle("-fx-background-color: gray");
}
}
Here is the second file that will contain the read and write methods, and the variables that store what is read. I can get them to print out to console as demonstrated below. They need to be appended to my already existing textArea readText.
package chapter17;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;
public class ReadWrite extends Exercise17_5 {
int[] numbers = {1, 2, 3, 4, 5};
public ReadWrite(){
};
public void write() throws IOException {
try (ObjectOutputStream output = new ObjectOutputStream(new FileOutputStream("Exercise17_5.dat"))){
output.writeObject(numbers);
output.writeObject(new Date());
output.writeDouble(2.5);
}
catch (IOException exception) {
exception.printStackTrace();
}
}
public void read() throws IOException {
try{
FileInputStream inputFile = new FileInputStream("Exercise17_5.dat");
ObjectInputStream input = new ObjectInputStream(inputFile);
int[] numbers = (int[])(input.readObject());
java.util.Date date = (java.util.Date)(input.readObject());
double decimal = (double)(input.readDouble());
for (int i = 0; i < numbers.length; i++){
System.out.print(numbers[i] + " ");
}
System.out.println();
System.out.println(decimal);
System.out.println(date);
input.close();
}
catch (IOException | ClassNotFoundException exception2){
exception2.printStackTrace();
}
}
}
I am reading two things from a JSON file:
actionOnPress:"robot.KeyPress(e)"
(robot being a java.awt.robot instance) and
event:"KeyEvent.VK_4"
I want to execute
robot.KeyPress(KeyEvent.VK_4)
what is the easiest way (best without needing to download libraries) to execute this? This code is supposed to also work with robot.mousePress and robot.mouseMove etc.
I already tried different things with ScriptEngine, but none of it seems to work.
Thank you very much, Kamik423
EDIT: should be universal. The user should be able to specify different events like FOR EXAMPLE robot
Ok, solved it myself. Here is the code:
package test;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.JFrame;
import javax.swing.JTextField;
import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class executor extends JFrame {
String import1 = "java.awt.Robot";
String import2 = "java.awt.event.KeyEvent";
String setup1 = "r = new Robot";
String executionType = "r.keyPress(event)";
String event = "KeyEvent.VK_4";
private JTextField textField;
static ScriptEngineManager manager = new ScriptEngineManager();
static ScriptEngine engine = manager.getEngineByName("JavaScript");
public executor() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100,100,100,100);
textField = new JTextField();
textField.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent ev) {
try {
engine.eval("importClass(" + import1 + ")");
engine.eval("importClass(" + import2 + ")");
engine.eval(setup1);
engine.eval(executionType.replaceAll("event", event));
} catch (ScriptException e) {
e.printStackTrace();
}
}
});
getContentPane().add(textField, BorderLayout.CENTER);
textField.setColumns(10);
}
public static void main(String[] args) {
executor ex = new executor();
ex.setVisible(true);
}
}