I'm doing a simple server/client communication for my tic tac toe game. All it goes through actionPerformed where I first setIcon to the pressed button, then proceed my performTurn method (there is some win checking), then send the coordinates of the pressed button to the client and then i wait for the other player to send me data about his turn. all it goes well, but......... the first method that should be made (setIcon) is actually done after receiving data from the other player. it goes like this: Game.performTurn, Server.send, Server.receive, setIcon. do anyone know what java issue is it, that the setIcon method doesnt go first? thx lot
public void actionPerformed(ActionEvent e) {
if (clickable && Game.getTurn()) {
clickable = false;
if (Board.player) {
setIcon(X);
Game.performTurn(x, y, Value.FIRST);
try {
Server.send(new ObjToSend(x, y));
} catch (IOException ex) {
Logger.getLogger(XOButton.class.getName()).log(Level.SEVERE, null, ex);
}
try {
ObjToSend bla = Server.recieve();
Board.buttons[bla.getX()][bla.getY()].setIcon(O);
Game.performTurn(bla.getX(), bla.getY(), Value.SECOND);
Game.turn = true;
} catch (IOException | ClassNotFoundException ex) {
Logger.getLogger(XOButton.class.getName()).log(Level.SEVERE, null, ex);
}
Related
I am doing desktop application using swing and want busy cursor to every event
current using code
try {
Cursor hourglassCursor =
Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR); this.setCursor(hourglassCursor);
doProcessing();
}
finally {
Cursor normalCursor = new Cursor(Cursor.DEFAULT_CURSOR);
this.setCursor(normalCursor);
}
I want apply global function that apply on every event
Please help me
You can create a method that sets Cursor to the Component
public void doProcessing(Component component, Runnable process){
if (component==null || process==null){
return;
}
component.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
SwingUtilities.invokeAndWait(process);
} catch (InterruptedException | InvocationTargetException e) {
e.printStackTrace();
}
component.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
I need your help please: I'm working on a little Java application (Java version 7) which has to be minimized into the system tray.
I'm using Class SystemTray, with SystemTray.isSupported(), then
SystemTray systemTray = SystemTray.getSystemTray();
ImageIcon icon = new javax.swing.ImageIcon(getClass().getResource("icon.png"));
[...]
systemTray.add(trayIcon);
(With popup of course)
On Windows, it's working great. On XFCE, Xubuntu, no problem, icon is working with popup. However on KDE and Gnome shell... it doesn't work.
KDE (4.14.1)
(Qt: 4.8.6 Tools Plasma: 4.11.12)
SystemTray.isSupported() = true and when the program arrived at the line:
systemTray.add(trayIcon); An exception is caught:
Error during Tray process:
java.awt.AWTException: TrayIcon couldn't be displayed.
Thereby the icon is white, and doesn't work when user clicks on it, no popup.
Gnome Shell (3.12.2)
SystemTray.isSupported() = true, the icon is located on notification area at the bottom, but mouse events don't work...
To fix these problem, I thought SWT could be a good idea. But when I implemented it (last version), I've got this warning:
WARNING **: Couldn't connect to accessibility bus: Failed to connect
to socket /tmp/[...]
And it doesn't work...
Edit: not anymore, I can fix the problem of SWT with an external class. The warning is not caused by SWT, but environment system probably (I had the same warning with other applications in the terminal).
So now, what can I do?
I think to check environment system with System.getenv("XDG_CURRENT_DESKTOP") & System.getenv("GDMSESSION") and then enable or disable system tray if it is KDE or Gnome 3... but this solution is not really good because of it is a local solution for multi-platform (in function of OS I mean), and not a global solution (one method for all OS)...
So, other idea? I don't know... is there a way to define an embedded JWindow into the system tray?
I have run up against this problem myself, and as I recall I ran up against a brick wall in sorting it out with a legitimate solution. I traced the problem to a call to the TrayIcon.addNotify() method randomly failing. I seem to recall this was because of a race condition in the internals where a call to the X11 system was taking too long to complete so the java side was giving up.
But if you have a ninja PC with a decent graphics card you would probably never meet this situation, which is probably why it hasn't been fixed yet. My dev machine is on the slow side so it was happening to me about 50% of the time.
I did hack a quick and dirty solution together, which involves trying to call addNotify repeatedly (with a pause inbetween each attempt) until it succeeds (or has failed a maximum number of times). Unfortunately the only way to do this was via reflection as the addNotify method is package-private.
Code follows:
public class HackyLinuxTrayIconInitialiser extends SwingWorker<Void, TrayIcon> {
private static final int MAX_ADD_ATTEMPTS = 4;
private static final long ADD_ICON_DELAY = 200;
private static final long ADD_FAILED_DELAY = 1000;
private TrayIcon[] icons;
public HackyLinuxTrayIconInitialiser(TrayIcon... ic) {
icons = ic;
}
#Override
protected Void doInBackground() {
try {
Method addNotify = TrayIcon.class.getDeclaredMethod("addNotify", (Class<?>[]) null);
addNotify.setAccessible(true);
for (TrayIcon icon : icons) {
for (int attempt = 1; attempt < MAX_ADD_ATTEMPTS; attempt++) {
try {
addNotify.invoke(icon, (Object[]) null);
publish(icon);
pause(ADD_ICON_DELAY);
break;
} catch (NullPointerException | IllegalAccessException | IllegalArgumentException e) {
System.err.println("Failed to add icon. Giving up.");
e.printStackTrace();
break;
} catch (InvocationTargetException e) {
System.err.println("Failed to add icon, attempt " + attempt);
pause(ADD_FAILED_DELAY);
}
}
}
} catch (NoSuchMethodException | SecurityException | NoSuchFieldException e1) {
Log.err(e1);
}
return null;
}
private void pause(long delay) {
try {
Thread.sleep(delay);
} catch (InterruptedException e1) {
Log.err(e1);
}
}
#Override
protected void process(List<TrayIcon> icons) {
for (TrayIcon icon : icons) {
try {
tray.add(icon);
} catch (AWTException e) {
Log.err(e);
}
}
}
}
To use it, just call:
if (<OS is Linux>) {
new HackyLinuxTrayIconInitialiser(ticon, micon, licon).execute();
} else {
try {
tray.add(ticon);
tray.add(micon);
tray.add(licon);
} catch (AWTException e) {
Log.err(e);
}
}
I seem to recall at the time I couldn't just keep calling SystemTray.add(icon) as it this would leave "ghost" trayicons behind on the system tray if I did.
Hope this helps.
I will start off by explicitly stating my main question: what is the correct way to create midi events with the correct 'tick' from ShortMessages with the correct microsecond position when using the Java synthesizer to record to the Java sequencer?
I've been trying to figure this out for several days. My little midi program is quite simple, or should be, at least. There's a piano layout and three buttons. The piano, which uses the synthesizer, works great; you can play notes with the mouse or your computer keyboard.
I've read the Oracle Docs instructions backwards and forwards (and lots of forum threads), but clearly I'm missing something.
Currently I can get the sequencer to record by manually creating a ShortMessage, a MidiEvent, and sending them to the sequencer/add them to the track, but it will only record once. The play back also plays them back with usually the wrong timing. Here's the code that executes these: (if you want me to post additional or all of the code let know).
The code for what happens when I click the record/stop/buttons:
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand() == "Record")
{
mySeq.deleteTrack(track);
track = mySeq.createTrack();
try {
seq.setSequence(mySeq);
} catch (InvalidMidiDataException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
seq.recordEnable(track, ChannelNum);
seq.startRecording();
}
else if(e.getActionCommand() == "Stop")
{
seq.stop();
}
else if(e.getActionCommand() == "Play")
{
mySeq.deleteTrack(track);
track = mySeq.createTrack();
addEvents(track);
seq.setTickPosition(10);
seq.start();
}
}
This is the code for when the user plays a note on the piano:
// The Mouse presses a key, the note on the channel is turned on
// A MidiEvent and ShortMessage are created using the CreateOnEvent method
public void mousePressed (MouseEvent e) {
Key key = (Key) e.getSource ();
channel.noteOn (key.getNote (), 127);
CreateOnEvent(key);
}
public void mouseReleased (MouseEvent e) {
Key key = (Key) e.getSource ();
channel.noteOff (key.getNote ());
CreateOffEvent(key);
}
public void mouseClicked (MouseEvent e) { }
public void mouseEntered (MouseEvent e) { }
public void mouseExited (MouseEvent e) { }
And finally here's the CreateOnEvent Method:
// I originally was sending the events directly to the sequencer
// but here I'm adding the events to an ArrayList of MidiEvents to attempt a work around
// I can then add those events to a track to play them
public void CreateOnEvent(Key key)
{
if(seq.isRecording())
{
ShortMessage myMsg = new ShortMessage();
try {
myMsg.setMessage(ShortMessage.NOTE_ON, ChannelNum, key.getNote(), 127);
} catch (InvalidMidiDataException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
long timeStamp = synth.getMicrosecondPosition();
long tick = seq.getTickPosition();
event = new MidiEvent(myMsg, tick);
seqReceiver.send(myMsg, timeStamp);
Events.add(event);
}
}
I'm using this code
private void botaoGrafADMouseClicked(java.awt.event.MouseEvent evt) {
try {
boolean[] b=new boolean[8];
if (Caixa9.isSelected()) b[0]=true; else b[0]=false;
if (Caixa11.isSelected()) b[1]=true; else b[1]=false;
if (Caixa10.isSelected()) b[2]=true; else b[2]=false;
if (Caixa12.isSelected()) b[3]=true; else b[3]=false;
b[4]=false;b[5]=false;b[6]=false;b[7]=false;
final LineChartDemo1 demo = new LineChartDemo1("Leitura A/D",b,"outad.txt",4);
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(Comunicacao.class.getName()).log(Level.SEVERE, null, ex);
}
}
to call an graph interface. But, when I do this, every time I call the graph, it generates on new window and, if I close on of these windows, the whole program is closed.
I'd want to know what am I doing wrong. How Can I avoid this (I would post a printscreen, but, as new user, I can't, it is on http://i.stack.imgur.com/4JLxQ.png I think
Edit: Image
JFrame has a default close operation (i.e. what happens when you close the window using your window manager) of EXIT_ON_CLOSE. Use JFrame.setDefaultCloseOperation to set a different value.
I don't know what the class LineChartDemo1 is, but you could probably set it as the content of a JDialog and call setDefaultCloseOperation (JDialog.DISPOSE_ON_CLOSE) on each dialog. This way, when the user closes the dialog, only that window will close, the others will remain open.
I created a new netbeans JFrame and made reference to it like this:
InterfaceGrafico minhaInterface = new InterfaceGrafico("Leitura I/O",b,"outio.txt",8);
where the arguments where the same to generate the graph. In this "InterfaceGrafico" class:
public InterfaceGrafico(final String title,boolean[] b, String nomeArquivo, int col) {
try {
initComponents();
final LineChartDemo1 demo = new LineChartDemo1("Leitura I/O", b, "outio.txt", 8);
demo.pack();
RefineryUtilities.centerFrameOnScreen(demo);
demo.setVisible(true);
} catch (IOException ex) {
Logger.getLogger(InterfaceGrafico.class.getName()).log(Level.SEVERE, null, ex);
}
}
That means, I just shifted the code to another JFrame. I also commented the public void run method . Now I can close each graph generated without closing the whole application and the other generated graphs. In the "LineChart1" class, I added this
public void windowClosing(final WindowEvent evt){
if(evt.getWindow() == this){
dispose();
}
}
I am displaying a confirmation dialog in Java using JOptionPane.showConfirmDialog. The dialog shows a Yes No confirmation to the user. This is called as follows:
int result = JOptionPane.showConfirmDialog(sessionObjects.getActiveComponent(),
"Are you sure you want to exit?", "My App", JOptionPane.YES_NO_OPTION);
The question is as this is a simple confirmation, can the user press y for yes and n for no? At present the user has to click on the buttons?
Thanks,
Andez
There is another simpler possibility: you can press alt in a program and then release it in a same way:
public static void pressAlt(){
try {
Robot r = new Robot();
r.keyPress(KeyEvent.VK_ALT);
} catch (AWTException ex) {
Logger.getLogger(ManualDetection.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void releaseAlt(){
try {
Robot r = new Robot();
r.keyRelease(KeyEvent.VK_ALT);
} catch (AWTException ex) {
Logger.getLogger(ManualDetection.class.getName()).log(Level.SEVERE, null, ex);
}
}
then when you call:
pressAlt();
int confirm = JOptionPane.showConfirmDialog(... bla bla bla ...
,JOptionPane.YES_NO_OPTION);
releaseAlt();
the behavior is exactly the same, as you desired...
You already have "hotkeys" (mnemonics) for the buttons: Alt+Y for "Yes" and Alt+N for "No".
You can also hit Tab to toggle between them and Space to press.
No, but you can create your own JDialog that could do that.
Look at Stopping Automatic Dialog Closing