am I overloading my actionListener? JFileChooser - java

I am attempting to load a saved file from JFileChooser using an actionListener. Here is a snippet of code.
class chooserListener implements ActionListener{
public void actionPerformed (ActionEvent e)
{
if (e.getSource() instanceof JFileChooser){
JFileChooser openFile = (JFileChooser)e.getSource();
String command = e.getActionCommand();
if (command.equals(JFileChooser.APPROVE_SELECTION)){
File selectedFile = openFile.getSelectedFile();
loadSavedGame(selectedFile);
System.out.print("clicked open file");
tp.setSelectedIndex(0);
}
else if (command.equals(JFileChooser.CANCEL_SELECTION)) {
System.out.print("tester");
tp.setSelectedIndex(0);
}
}
}
}
chooser.addActionListener(new chooserListener());
public void loadSavedGame(File loadfile) {
int allCells = countCells(loadfile);
setMineGame(allCells);
try {
Scanner loadFile = new Scanner(loadfile);
while (loadFile.hasNextInt()){
for (int i = 0; i < allCells; i++){
mineGame.setCell(i, loadFile.nextInt());
//System.out.print("loading saved game");
}
loadFile.close();
mineGame.repaint();
tp.setSelectedIndex(0);
}
}
catch (FileNotFoundException e) {
e.printStackTrace();
}
}
private int countCells(File countCell) {
int cellCount = 0;
try {
Scanner getCells = new Scanner(countCell);
while (getCells.hasNextInt()){
cellCount++;
}
getCells.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(cellCount);
return cellCount;
}
public void setMineGame(int cells) {
game.removeAll();
mineGame.setDifficulty(cells);
mineGame = new Board(statusbar, difficulty);
game.add(mineGame, BorderLayout.CENTER);
game.add(statusbar, BorderLayout.SOUTH);
frame.validate();
frame.repaint();
}
public void setDifficulty(int cells){
if(cells == 256){
difficulty = 0;
}
if (cells == 676){
difficulty = 1;
}
else difficulty = 2;
}
I feel like I have too many methods for the action listener to do. It is hanging when I click 'open', and the test print line 'System.out.print("clicked open file");' does not print. the rest of my code is really large and I'm not sure how to to an SSCE(?). I'm wondering if anyone can see why my actionListener is hanging? thanks IA

It seems like loadSavedGame(File file) takes a lot of time to execute. As this method is running in the Event Dispatch Thread you feel like your program is hanging and never reaches System.out.print("clicked open file"); line. I'd start testing the time of response for this method in a separate test case
Anyway I'd suggest you a few tips:
1) Note there's no need to implement an ActionListener to do your code. You can simple make this:
JFileChooser chooser = new JFileChooser();
int returnValue = chooser.showOpenDialog(null);
if(returnValue == JFileChooser.APPROVE_OPTION){
//make stuff if approved
} else if(returnValue == JFileChooser.CANCEL_OPTION){
//make stuff if canceled
}
I think it makes people life easier.
2) On the other hand note you have two I/O operations: getting the cells count through countCells(File countCell) method and getting the cells themselves inside loadSavedGame(File loadfile) method. You can do it better reading the file just once:
public List<Integer> getCells(File file){
List<Integer> list = new ArrayList<>();
try {
Scanner getCells = new Scanner(file);
while (getCells.hasNextInt()){
list.add(Integer.valueOf(getCells.nextInt()));
}
getCells.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
return list;
}
}
And make this change in loadSavedGame method:
public void loadSavedGame(File loadfile) {
List<Integer> allCells = getCells(loadfile);
setMineGame(allCells.size());
int index = 0;
for(Integer value : allCells){
mineGame.setCell(index, value);
index++;
}
mineGame.repaint();
tp.setSelectedIndex(0);
}

Related

Java exe won't display specific jframe but IDE will

I've created a mini quiz game in java and wanted to convert it to an exe..It has photos and sounds attached to it but they are in their respective folders and with the correct paths. When i click on "Insert a new question" the exe works fine, the same thing happens for the "exit" option. But when i click "Play" no window pops up but i don't get an error either..
I tried placing the photos and sounds in the same folder as the class that uses them but it didn't fix the problem. I also tried inserting ".." at the beginning of the URL paths but it didn't fix it either. I've attached the code for the not showing frame.
ArrayList<Question> questions;
int selectedQuestion = 0;
int remainingLife = 3;
Random random = new Random();
int fillAnswer = 0;
String [] answerArray = new String[4];
Clip clipSuccess;
Clip clipFailure;
Clip clipGameOver;
public static Mixer mixer;
public static Clip clip;
javax.swing.Timer timer = new javax.swing.Timer(1000, new java.awt.event.ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
timer.stop();
jLabel5.setIcon(null);
playRound();
}
});
public PlayGame() {
initComponents();
questions = new ArrayList<Question>();
populateArrayList();
clipSuccess = setSound("../Sounds/success.wav");
clipFailure = setSound("../Sounds/failure.wav");
clipGameOver = setSound("../Sounds/gameOver.wav");
playRound();
}
public void populateArrayList(){
try{
FileInputStream file = new FileInputStream("Questions.dat");
ObjectInputStream inputFile = new ObjectInputStream(file);
boolean endOfFile = false;
while(!endOfFile){
try{
questions.add((Question) inputFile.readObject());
}
catch(EOFException e){
endOfFile = true;
}
catch(Exception f){
JOptionPane.showMessageDialog(null, f.getMessage());
}
}
inputFile.close();
}
catch(IOException e){
JOptionPane.showMessageDialog(null, e.getMessage());
}
}
public Clip setSound(String soundPath){
Mixer.Info[] mixInfos = AudioSystem.getMixerInfo();
/*for(Mixer.Info info: mixInfos){
System.out.println(info.getName() + "----" + info.getDescription());
}*/
mixer = AudioSystem.getMixer(mixInfos[3]);
DataLine.Info dataInfo = new DataLine.Info(Clip.class, null);
try {
clip = (Clip)mixer.getLine(dataInfo);
}
catch(LineUnavailableException lue){
lue.printStackTrace();
}
try{
URL soundURL = PlayGame.class.getResource(soundPath);
AudioInputStream audioStream = AudioSystem.getAudioInputStream(soundURL);
clip.open(audioStream);
}
catch(LineUnavailableException lue){
lue.printStackTrace();
}
catch(UnsupportedAudioFileException uofe){
uofe.printStackTrace();
}
catch(IOException ioe){
ioe.printStackTrace();
}
return clip;
}
public void successAnswer(){
JOptionPane.showMessageDialog(null, "Απάντησες σωστά!");
jLabel5.setText("");
jLabel5.setIcon(new ImageIcon(PlayGame.class.getResource("../Images/Fireworks-animated.gif")));
clipSuccess.setFramePosition(0);
clipSuccess.start();
timer.start();
}
public void wrongAnswer(){
remainingLife--;
JOptionPane.showMessageDialog(null, "Απάντησες λάθος..");
jLabel5.setText("");
jLabel5.setIcon(new ImageIcon (PlayGame.class.getResource("../Images/failure.gif")));
if (remainingLife == 0){
clipFailure.setFramePosition(0);
clipFailure.start();
timer.start();
JOptionPane.showMessageDialog(null, "Δυστυχώς έχασες..");
clipGameOver.setFramePosition(0);
clipGameOver.start();
do{
try{
Thread.sleep(50);
}
catch(InterruptedException ie){
ie.printStackTrace();
}
}while(clipGameOver.isActive());
System.exit(0);
}
clipFailure.setFramePosition(0);
clipFailure.start();
timer.start();
}
public void playRound(){
selectedQuestion = random.nextInt(questions.size());
jTextField3.setText(Integer.toString(remainingLife));
jTextArea2.setText(questions.get(selectedQuestion).getQuestionName());
for (int i=0; i<4; i++){
fillAnswer = random.nextInt(questions.size());
answerArray[i] = questions.get(fillAnswer).getQuestionAnswer();
if (i==2){
answerArray[i] = questions.get(selectedQuestion).getQuestionAnswer();
continue;
}
}
Collections.shuffle(Arrays.asList(answerArray));
jComboBox1.setModel(new javax.swing.DefaultComboBoxModel<>(answerArray));
}
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
// TODO add your handling code here:
int selectedAnswer = jComboBox1.getSelectedIndex();
jLabel5.setIcon(null);
if (questions.get(selectedQuestion).getQuestionAnswer().trim().equals(answerArray[selectedAnswer].trim())){
successAnswer();
}
else{
wrongAnswer();
}
timer.start();
}
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
System.exit(0);
In the IDE the output is a jframe with a question, a combo box of 4 answers, the player's life points and two buttons (one for locking the answer and one for exiting the program). But in the exe form it doesn't even pop up.
EDIT - This is the error the wrapper program shows:
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/netbeans/lib/awtextra/AbsoluteLayout
at quiz.PlayGame.initComponents(PlayGame.java:277)
at quiz.PlayGame.(PlayGame.java:62)

How to run a thread step by step using a jButton

i have a thread running which keeps repainting the maze recursively until the exit is reached. The method below is responsible for repainting the maze.
private void moveFromStep(int x, int y) {
if(step){
if(isWall(x,y))
return ;
if(isVisited(x,y))
return ;
if(isGoal(x,y)){
free = true;
JOptionPane.showMessageDialog(this, "Solution Complete: finish reachable");
}
if(!free){
step = false;
setVisited(x,y);
repaint();
//try {Thread.sleep(3000);} catch (Exception e) { }
//try {wait();} catch (Exception e) { }
moveFromStep(x-1,y);
moveFromStep(x+1,y);
moveFromStep(x,y-1);
moveFromStep(x,y+1);
}
}
}
now i have a JPanel running separately and i want to repaint it step by step.
i want to do this by using a "Step" button. So like the maze is printed step by step when "Step" button is pressed. The code below is the action listener for the buttons
public void actionPerformed(ActionEvent event) {
String action = event.getActionCommand();
MazeStep mazeStep = new MazeStep();
Thread mazeThreadStep = null;
if (action.equals("Load Maze")) {
mazeAnim.readFile(getName());
//mazeStep = new MazeStep();
mazeStep.readFile(getName());
}
else if(action.equals("Start")){
JFrame world = new JFrame();
mazeStep = new MazeStep();
mazeStep.readFile(getName());
world.setSize(300, 300);
world.setTitle("Maze solver");
world.setContentPane(mazeStep);
world.setVisible(true);
mazeThreadStep = new Thread(mazeStep);
mazeThreadStep.start();
}
if(action.equals("Step")){
mazeStep.step = true;
synchronized (mazeThreadStep) {
mazeThreadStep.notify();
}
}
}
So can anyone help me what could be done in order to achieve this plz.

Thread.join does not seem to work in my code; am I using it right?

I have a class Automator that can automate a user. I am specifically having problems setting the system clipboard in windows. The Automator class makes use of the ClipSetThread class, which is a thread that sets the system clipboard. A instance of ClipSetThread takes as input a thread, that if null, it joins with (waits for it to complete).
I feel that I am not calling ClipSetThread right because I still have the errors I have had before in its reliability; prior to the ClipSetThread. This code does not throw any errors when it runs, it works about 2/3 of the time though. Other times it will print 1134, _234, or etc. It seems that the threads are not joining (waiting for) each other, or get skipped.
Code:
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;
import org.jnativehook.GlobalScreen;
import org.jnativehook.NativeHookException;
import org.jnativehook.mouse.NativeMouseEvent;
import org.jnativehook.mouse.NativeMouseInputListener;
public class Automator extends Thread implements NativeMouseInputListener
{
Robot rob = null;
TheAppClass theApp = null;
ClipSetThread lastClipSet = null;
boolean doit = false;
boolean settingClip = false;
public void run()
{
try // to make the Global hook
{
GlobalScreen.registerNativeHook();
}
catch (NativeHookException ex){theApp.updateOutput("No Global Keyboard or Mouse Hook");return;}
try // to create a robot (can simulate user input such as mouse and keyboard input)
{
rob = new Robot();
}
catch (AWTException e1) {theApp.updateOutput("The Robot could not be created");return;}
while(true) {}
}
public void setApp(TheAppClass app)
{
theApp = app;
theApp.updateOutput("Succesfully started automator");
}
public void setClip(String arg)
{
ClipSetThread set = new ClipSetThread(theApp, lastClipSet);
lastClipSet = set;
set.setClip(arg);
}
public void DOit()
{
theApp.updateOutput("Starting");
pasteAtCursorLocation("1");
tab(1);
pasteAtCursorLocation("2");
tab(1);
pasteAtCursorLocation("3");
tab(1);
pasteAtCursorLocation("4");
tab(1);
theApp.updateOutput("Complete");
}
public void nativeMouseReleased(NativeMouseEvent e)
{
//System.out.println("Mouse Released: " + e.getButton());
if(doit)
{
DOit();
doit = false;
}
}
public void pasteAtCursorLocation(String text)
{
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
}
public void tab(int numTimes)
{
while(numTimes > 0)
{
rob.keyPress(KeyEvent.VK_TAB);
rob.keyRelease(KeyEvent.VK_TAB);
numTimes--;
theApp.updateOutput("Simulated Tab");
}
}
// Unimplemented
public void nativeMouseClicked(NativeMouseEvent arg0) {}
public void nativeMousePressed(NativeMouseEvent arg0) {}
public void nativeMouseDragged(NativeMouseEvent arg0) {}
public void nativeMouseMoved(NativeMouseEvent arg0) {}
}
ClipSetThread:
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
public class ClipSetThread extends Thread
{
Clipboard sysClip = null;
TheAppClass theApp = null;
public ClipSetThread(TheAppClass app, Thread waitFor)
{
theApp = app;
sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
if(waitFor != null)
{try {waitFor.join();}catch (InterruptedException e) {}}
}
public void setClip(String arg)
{
// Two strings that will hopefully never be on the clipboard
String checkStr1 = "9999999999999";
String checkStr2 = "99999999999999";
// When we read in the clipboard we want to see if we change these strings from the ones they
// will never be, if they do change we read the clipboard successfully
String clipBoardTextBefore = checkStr1;
String clipBoardTextAfter = checkStr2;
// First get a copy of the current system clipboard text
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// If we failed to change the string it means we failed to read the text
if(clipBoardTextBefore.equals(checkStr1))
theApp.updateOutput("Could NOT get sysClip text");
else
{
// If we didn't failed to get the current text try to change it
while(true)
{
try{sysClip.setContents(new StringSelection(arg), null);}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// Now again check to see the clipboard text
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextAfter = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
// If we failed to read the clipboard text
if(clipBoardTextAfter.equals(checkStr2))
theApp.updateOutput("Could NOT check if sysClip update was successful");
else
{ // We re-read the clipboard text, see if it changed from the original clipboard text
if(clipBoardTextAfter.equals(checkStr1))
theApp.updateOutput("Could NOT successfully set clipboard text");
else
theApp.updateOutput("Set Clipboard Text:" + arg + "\n");
}
}
}
}
So, firstly, you never call start on the ClipSetThread. You should also check to see if the thread is still alive before joining it.
public class ClipSetThread extends Thread {
Clipboard sysClip = null;
TheAppClass theApp = null;
private String toClipboard;
public ClipSetThread(TheAppClass app, Thread waitFor, String toClipBoard) {
theApp = app;
sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
this.toClipboard = toClipBoard;
// !! Check to see if the thread is also alive before trying to join with it...
if (waitFor != null && waitFor.isAlive()) {
try {
waitFor.join();
} catch (InterruptedException e) {
}
}
}
// You should really put your logic into the `run` method in order to allow
// the code to actually run in a separate thread...otherwise there is no
// point in using a thread....
#Override
public void run() {
// Two strings that will hopefully never be on the clipboard
String checkStr1 = "9999999999999";
String checkStr2 = "99999999999999";
// When we read in the clipboard we want to see if we change these strings from the ones they
// will never be, if they do change we read the clipboard successfully
String clipBoardTextBefore = checkStr1;
String clipBoardTextAfter = checkStr2;
// First get a copy of the current system clipboard text
while (true) {
try {
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// If we failed to change the string it means we failed to read the text
if (clipBoardTextBefore.equals(checkStr1)) {
theApp.updateOutput("Could NOT get sysClip text");
} else {
// If we didn't failed to get the current text try to change it
while (true) {
try {
sysClip.setContents(new StringSelection(toClipboard), null);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// Now again check to see the clipboard text
while (true) {
try {
Transferable contents = sysClip.getContents(null);
clipBoardTextAfter = (String) contents.getTransferData(DataFlavor.stringFlavor);
} catch (Exception e) {
try {
Thread.sleep(20);
} catch (InterruptedException e1) {
}
continue;
}
break;
}
// If we failed to read the clipboard text
if (clipBoardTextAfter.equals(checkStr2)) {
theApp.updateOutput("Could NOT check if sysClip update was successful");
} else { // We re-read the clipboard text, see if it changed from the original clipboard text
if (clipBoardTextAfter.equals(checkStr1)) {
theApp.updateOutput("Could NOT successfully set clipboard text");
} else {
theApp.updateOutput("Set Clipboard Text:" + toClipboard + "\n");
}
}
}
}
}
As per our previous converstaion, it's dangerous to use while (true) {}, it's also wasteful, as it will consume CPU cycles unnecessarily...
public class Automator extends Thread implements NativeMouseInputListener {
// A "locking" object...
private static final Object WAIT_LOCK = new Object();
Robot rob = null;
TheAppClass theApp = null;
ClipSetThread lastClipSet = null;
boolean doit = false;
boolean settingClip = false;
public void run() {
try // to make the Global hook
{
GlobalScreen.registerNativeHook();
} catch (NativeHookException ex) {
theApp.updateOutput("No Global Keyboard or Mouse Hook");
return;
}
try // to create a robot (can simulate user input such as mouse and keyboard input)
{
rob = new Robot();
} catch (AWTException e1) {
theApp.updateOutput("The Robot could not be created");
return;
}
// This is wasteful...
// while (true) {
// }
// Locks do not consume CPU cycles while in the wait state...
synchronized (WAIT_LOCK) {
try {
WAIT_LOCK.wait();
} catch (Exception exp) {
}
}
}
public void dispose() {
// Tell the thread it can terminate...
synchronized (WAIT_LOCK) {
WAIT_LOCK.notify();
}
// This will STOP the current thread (which called this method)
// while the lastClipSet finishes...
if (lastClipSet != null && lastClipSet.isAlive()) {
lastClipSet.join();
}
}
public void setClip(String arg) {
ClipSetThread set = new ClipSetThread(theApp, lastClipSet, arg);
lastClipSet = set;
// You MUST START the thread...
set.start();
}
/*...*/
}
Updated
This code could produce a infinite loop. What happens if the clipboard does not contain a String value??
while(true)
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
}
catch(Exception e)
{
try {Thread.sleep(20);} catch (InterruptedException e1) {}
continue;
}
break;
}
You tend to do this a lot. I might suggest that you provide some kind of "escape" mechanism to allow it to fail after a number of retries...
boolean successful = false;
int retries = 0;
while (!successful && retries < 20) {
{
try
{
Transferable contents = sysClip.getContents(null);
clipBoardTextBefore = (String)contents.getTransferData(DataFlavor.stringFlavor);
successful = true;
}
catch(Exception e)
{
retries++;
try {Thread.sleep(20);} catch (InterruptedException e1) {}
}
}
Updated with working example
Okay, that was fun. I've put together a (simple) working example. You will want to open a text editor of some kind. When you run the program, you have 5 seconds to make it active ;)
The only basic change I've made is I set added a auto delay between events of 250 milliseconds (see rob.setAutoDelay(250).
Now, you could also place a delay between each key event as well, using Robot#delay, but that's up to you
public class Engine extends Thread {
private Robot rob = null;
private PasteThread lastClipSet = null;
public void setClip(String arg) {
if (lastClipSet != null && lastClipSet.isAlive()) {
try {
lastClipSet.join();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
PasteThread set = new PasteThread(arg);
lastClipSet = set;
lastClipSet.start();
}
public void pasteAtCursorLocation(String text) {
System.out.println("Paste " + text);
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
}
public Engine() throws AWTException {
rob = new Robot();
rob.setAutoDelay(250);
try {
Thread.sleep(5000);
} catch (InterruptedException ex) {
}
pasteAtCursorLocation("This is a simple test, thanks for watching!");
}
public static void main(String[] args) {
try {
new Engine();
} catch (AWTException ex) {
Logger.getLogger(Engine.class.getName()).log(Level.SEVERE, null, ex);
}
}
public class PasteThread extends Thread {
private String toPaste;
public PasteThread(String value) {
toPaste = value;
}
#Override
public void run() {
Clipboard sysClip = Toolkit.getDefaultToolkit().getSystemClipboard();
System.out.println("Current clipboard contents = " + getClipboardContents(sysClip));
sysClip.setContents(new StringSelection(toPaste), null);
System.out.println("New clipboard contents = " + getClipboardContents(sysClip));
}
public String getClipboardContents(Clipboard clipboard) {
String value = null;
boolean successful = false;
int retries = 0;
while (!successful && retries < 20) {
Transferable contents = clipboard.getContents(null);
if (contents.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
value = (String) contents.getTransferData(DataFlavor.stringFlavor);
successful = true;
} catch (Exception exp) {
retries++;
exp.printStackTrace();
}
} else {
retries++;
}
}
System.out.println(successful + "/" + retries);
return value;
}
}
}
Could you please try to repeat the Paste action with a sleep 1 second in between
public void pasteAtCursorLocation(String text)
{
setClip(text);
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
// put in a sleep 1 second here
rob.keyPress(KeyEvent.VK_CONTROL);
rob.keyPress(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_V);
rob.keyRelease(KeyEvent.VK_CONTROL);
theApp.updateOutput("Simulated Paste");
}
It could be that pasting 2x is giving different results. The reason for this strange behavior could the way Windows manages the clipboard. If pasting 2x the clipboard is giving different result then you know that the root cause for this strange behavior is not to find in your code but how Java and Windows work together.

Jtable content is visible through different tab

I have JTabbedPane with 4 tabs. JtabbedPane is situated on a JLayeredPane. 1st and 4th tab contain JTable with custom models. Each of the tables is being refreshed every 5-10 seconds.
When 1st tab is active, and JTable on 4th has just finished refreshing, I can see content of the 4th on the 1st. Look at the screenshot.
When I click on the other tab, or minimize window, that strange effect is gone. Till the next refresh of that table on 4th tab. Refreshing is done using Future<> object.
I used Swing GUI builder in Netbeans, so I have huge amount of code. Would post any piece which could be useful.
I tried to revalidate jTabbedPane, is had no effect. Both tables and jScrollPanes has opaque property set to true. So I tried to use SwingUtilities.invokeLater(). It helped a little bit - now first content update goes well, but later - the same problem.
2nd table model has method to update it's content
public void setData(LinkedList<Object[]> __rows) {
NewDevsTableModel.__rows = __rows;
fireTableDataChanged();
}
It is used here (I added SwingUtilities here)
static class checkNew implements Callable<Boolean> {
#Override
public Boolean call() {
ServiceMessage sm = ServiceMessage.getNewList();
try {
connect();
os.write(sm.serialize());
for (int i=0; i<10; i++) {
try {
Thread.sleep(300);
} catch (InterruptedException e) {}
if (is.available() > 0) {
break;
}
if (i == 9) {
disconnect();
return false;
}
}
byte[] actByte = new byte[is.available()];
is.read(actByte);
try {
sm = ServiceMessage.Deserialize(actByte); //may be there are no new devices
if (sm.getType() == ServiceMessageType.NODATA) {
MainWindow.jTabbedPane1.setEnabledAt(3, false);
if (MainWindow.jTabbedPane1.getSelectedIndex() == 3) {
MainWindow.jTabbedPane1.setSelectedIndex(0);
}
return true;
} else {
return false; //wrong answer type
}
} catch (ClassCastException | StreamCorruptedException e) {
//remember selection and scroll
final int scroll = MainWindow.jScrollPane3.getVerticalScrollBar().getValue();
final int[] rows = MainWindow.newDevsTable.getSelectedRows();
int col = MainWindow.devicesTable.getSelectedColumn();
String[] parts = new String(actByte).split("\n");
final LinkedList<Object[]> l = new LinkedList();
for (int i=0; i<parts.length; i++) {
String[] dev = parts[i].split(";", -1);
String descr = dev[2];
boolean iptype = (!dev[3].equals("-"));
String address = dev[4];
boolean atmtype = (dev[5].equals("+"));
if (MainWindow.newDevsTable.getRowCount() >= (i+1)) {
if ((MainWindow.newDevsTable.getValueAt(i, 4) != null) && !MainWindow.newDevsTable.getValueAt(i, 4).equals("")) {
descr = MainWindow.newDevsTable.getValueAt(i, 4).toString();
}
}
Object[] o = {dev[0], dev[1], MainWindow.language[180], MainWindow.language[4], descr, iptype, address, atmtype};
l.add(o);
}
if (!l.isEmpty()) {
SwingUtilities.invokeLater( new Runnable() {
#Override
public void run() {
MainWindow.newDevsPanel.setVisible(true);
MainWindow.jTabbedPane1.setEnabledAt(3, true);
((NewDevsTableModel)MainWindow.newDevsTable.getModel()).setData(l);
ButtonColumn buttonColumn = new ButtonColumn(MainWindow.newDevsTable, addAction, 2, true);
buttonColumn = new ButtonColumn(MainWindow.newDevsTable, rejAction, 3, false);
//put selection back
for (int i=0; i<rows.length; i++) {
MainWindow.newDevsTable.addRowSelectionInterval(rows[i], rows[i]);
}
MainWindow.jScrollPane3.getVerticalScrollBar().setValue(scroll);
}
});
} else {
MainWindow.jTabbedPane1.setEnabledAt(3, false);
if (MainWindow.jTabbedPane1.getSelectedIndex() == 3) {
MainWindow.jTabbedPane1.setSelectedIndex(0);
}
}
return true;
}
} catch (IOException e) {
disconnect();
return false;
} catch (ClassNotFoundException e) {
return false;
}
}
}
I submit the task this way
public static Future<Boolean> checkNewDevices() {
final Future<Boolean> task;
task = service.submit(new checkNew());
return task;
}
To refresh automatically I use separate thread
public class CheckNewPassThread extends Thread {
int pause = 10000;
#Override
public void run() {
for (;;) {
HostConnection.checkNewDevices();
try {
Thread.sleep(pause);
} catch (InterruptedException e) {}
}
}
}
Which is started when the window is opened
private void formWindowOpened(java.awt.event.WindowEvent evt) {
HostConnection.getData();
HostConnection.getDeviceAddress();
RefreshData refreshThread = new RefreshData();
refreshThread.start();
new CheckNewPassThread().start();
}
OMG, the problem was in calling jTabbedPane.setEnabledAt(3, true) to already enabled tab. Swing is fascinating

Is it possible to throw a KeyEvent virtualy on a JTextfield?

Here is my problem I got my System.in that is redirected to a JTextField. Right now the user can press enter and it will send my text away. But my client will not have access to this JTextfield so i wanted to know if i could recreate the Enter key in my code.
public static JTextField jtfEntree = new JTextField();
public static TexfFieldStreamer ts = new TexfFieldStreamer(jtfEntree);
System.setIn(ts);
jtfEntree.addActionListener(ts);
//************************************************************************
private void commandLaunch(String command)
//************************************************************************
{
jtfEntree.setText(command);
//here is where i want to fire the key Enter
}
//************************************************************************
class TexfFieldStreamer extends InputStream implements ActionListener{
private JTextField tf;
private String str = null;
private int pos = 0;
public TexfFieldStreamer(JTextField jtf) {
tf = jtf;
}
public int read() {
//test if the available input has reached its end
//and the EOS should be returned
if(str != null && pos == str.length()){
str =null;
//this is supposed to return -1 on "end of stream"
//but I'm having a hard time locating the constant
return java.io.StreamTokenizer.TT_EOF;
}
//no input available, block until more is available because that's
//the behavior specified in the Javadocs
while (str == null || pos >= str.length()) {
try {
//according to the docs read() should block until new input is available
synchronized (this) {
this.wait();
}
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
//read an additional character, return it and increment the index
return str.charAt(pos++);
}
public void actionPerformed(ActionEvent arg0)
{
// TODO Auto-generated method stub
str = tf.getText() + "\n";
pos = 0;
synchronized (this) {
//maybe this should only notify() as multiple threads may
//be waiting for input and they would now race for input
this.notify();
}
}
}
If you need more information ask in comments!
thank you for your help
P.S.: I did try to change the action listener to a document listener but it doesnt always fire the event so it didnt act like i wanted to.
Tried with the Robot but it seems like the textfield isnt getting the focus so the key is just pressed and nothing happens
//************************************************************************
protected static void commandExecute(String Command) //COMMAND EXECUTE
//************************************************************************
{
jtfEntree.setText(Command);
jtfEntree.requestFocus();
Robot robot;
try {
robot = new Robot();
robot.keyPress(KeyEvent.VK_ENTER);
} catch (AWTException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
jtfEntree.setText("");
}
//************************************************************************
Dont know if this would be of help. But did you try the robot class?
Robot robot = new Robot();
robot.keyPress(KeyEvent.VK_ENTER);
Would simulate a key press for Enter.
Does this help?

Categories