Malformed Farsi characters on AWT - java

When I started programming with the JDK6, I had no problem with text components, neither in AWT nor in Swing.
But for labels or titles of AWT components I do have a problem. I can't display Farsi characters on AWTs components (in Swing I type them into the source code).
Here's my sample code:
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.Properties;
public class EmptyFarsiCharsOnAWT extends JFrame{
public EmptyFarsiCharsOnAWT() {
super("مثال");
setDefaultCloseOperation(3);
setVisible(rootPaneCheckingEnabled);
}
public static void main(String[] args) throws AWTException, IOException {
JFrame jFrame = new EmptyFarsiCharsOnAWT();
MenuItem show ;
// approach 1 = HardCoding :
/*
show = new MenuItem("\u0646\u0645\u0627\u06cc\u0634");
*
*/
// approach 2 = using simple utf-8 saved text file :
/*
BufferedReader in = new BufferedReader(new FileReader("farsiLabels.txt"));
String showLabel = in.readLine();
in.close();
show = new MenuItem(showLabel);
*
*/
// approach 3 = using properties file :
FileReader in = new FileReader("farsiLabels.properties");
Properties farsiLabels = new Properties();
farsiLabels.load(in);
show = new MenuItem(farsiLabels.getProperty("tray.show"));
PopupMenu popUp = new PopupMenu();
popUp.add(show);
// creating Tray object
Image iconIamge = Toolkit.getDefaultToolkit().getImage("greenIcon.png");
TrayIcon trayIcon = new TrayIcon(iconIamge, null, popUp);
SystemTray tray = SystemTray.getSystemTray();
tray.add(trayIcon);
jFrame.setIconImage(iconIamge);
}
}
These three approaches all work when run with an IDE, but when I make a JAR containing this class (by means of NetBeans > project > clean & build), I don't see the expected characters (it shows EMPTY/BLANK SQUARES)!
Note:
It seems I can not attach anything, so the contents of the text file would be this: نمایش and the contents of properties file:
#Sun May 02 09:45:10 IRDT 2010
tray.show=نمایش
And I think I have to let you know that I posted this question a while ago on SDN and "the Java Ranch" forums and other native forums and still I'm waiting...
By the way I am using latest version of Netbeans IDE...
I will be grateful if anybody has a solution to these damn AWT components never rendering any Farsi character for me...

I suspect that this is platform related. Your example appears to work on my platform using approach 1 in either Netbeans or the command line; I didn't try the other approaches.
There might be a disparity between the IDE and the command line with regard to the default character encoding. I've noticed that NetBeans, Eclipse and many consoles can be set to something other than the platform default. Here's code to check:
System.out.println(System.getProperty("file.encoding"));
System.out.println(Charset.defaultCharset().name());
You might look at this related question, too.
Addendum: Note show string changed to match the JFrame title for comparison. The title and menu look the same from NetBeans' Run > Run Project as well as via these command lines:
$ java -cp build/classes EmptyFarsiCharsOnAWT
$ java -jar dist/test6.jar
import javax.swing.*;
import java.awt.*;
import java.io.*;
public class EmptyFarsiCharsOnAWT extends JFrame{
public EmptyFarsiCharsOnAWT() {
super("مثال");
setDefaultCloseOperation(3);
setVisible(rootPaneCheckingEnabled);
}
public static void main(String[] args) throws AWTException, IOException {
JFrame jFrame = new EmptyFarsiCharsOnAWT();
MenuItem show ;
// approach 1 = HardCoding :
show = new MenuItem("\u0645\u062b\u0627\u0644");
PopupMenu popUp = new PopupMenu();
popUp.add(show);
// creating Tray object
Image iconIamge = Toolkit.getDefaultToolkit().getImage("image.jpg");
TrayIcon trayIcon = new TrayIcon(iconIamge, null, popUp);
SystemTray tray = SystemTray.getSystemTray();
tray.add(trayIcon);
jFrame.setIconImage(iconIamge);
}
}

The most exciting part of your reply was:
"$ java -jar dist/test6.jar" !
Does it really shows the real characters (just like the frame title)?!
and not boxes or garbage ?
I'm sorry if I believe it hard, because the only problem in my developing work with Java took such long without any answer nor from searching, nor asking in forums is this!
So, what can I do? what font should I use? Unfortunately I'm not so familiar with fonts, until now I've just used global fonts in Java (Serif,SansSerif,etc.) and only modified their size or style, but after you suggest I examined several Persian ttf fonts through these codes:
File fontFile = new File("F_JADID.TTF");
Font font = Font.createFont(Font.TRUETYPE_FONT, fontFile);
show.setFont(font.deriveFont(15f));
but just boxes was the result! (just using HardCoding)
I think i should mention that my envirounment is win xp and i have this problem not only in my machine, but another running xp os too. And I'm using jdk6u17.
I can be agree with you in suspecting the fonts, because encoding problem (in my experience) appears with question mark, but garbage or empty boxes related to rendering characters.
But still i have the problem, just like the first day :(
What font you use and another question i encountered is:
Why swing doesn't have any problem without specifying the font, but AWT.
Addendum: Thanks to Oscar Reyes in this page for giving this link and thanks to StackOverflow :)
They saved me! from this section i should quote:
An application using peered AWT components can only use logical font names.
and from this section should quote:
For applications using AWT peered components, Sun's JREs select fonts for Chinese, Japanese, or Korean only when running on host operating systems localized for these specific languages
Yes, you guess right! by setting the OS locale to Farsi, i got the right result.
but i still should research and see how is it possible to have the right result by not setting the right locale, from that article.
I will explain how, when i got the result, but still will listen to here. wish me luck.

Related

How to force ImageJ to close all its windows without close event error?

I am writing a Java application for image analysis which at one point opens ImageJ with
ImageJ ij = new ImageJ();
and also opens a Windows containing an ImagePlus.
Now, whenever one closes ImageJ first, the ImagePlus will not close when pushing the close button. The other way around works, however in both cases an exception is thrown after closing ImageJ:
java.lang.reflect.InvocationTargetException
at java.awt.EventQueue.invokeAndWait(EventQueue.java:1288)
at java.awt.Window.doDispose(Window.java:1209)
at java.awt.Window.dispose(Window.java:1147)
at ij.ImageJ.run(ImageJ.java:784)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.IllegalArgumentException: null source
at java.util.EventObject.<init>(EventObject.java:56)
at java.awt.AWTEvent.<init>(AWTEvent.java:337)
at java.awt.event.InvocationEvent.<init>(InvocationEvent.java:285)
at java.awt.event.InvocationEvent.<init>(InvocationEvent.java:174)
at sun.awt.X11.XBaseMenuWindow.dispose(XBaseMenuWindow.java:907)
...
I don't know whether it is related as it happens in both cases.
Any suggestions on how to force ImageJ to close all its windows?
The exception
This happens when using OpenJDK 7 on Linux. The exception is fixed in Java 8.
Also: note that that exception is not the actual cause of the quitting issue you are seeing.
The disposal problem
ImageJ 1.x's application disposal is a convoluted mess. (See this news post for some technical discussion.) It was really intended primarily to run as a standalone application, and is mostly tested with the exitWhenQuitting flag set to true such that the JVM shuts down upon closure of the main window. So it is not surprising that using ImageJ in a different fashion results in hanging image windows.
I have tested various workarounds—e.g.:
ij.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(final WindowEvent e) {
// dispose all image windows
for (final int id : WindowManager.getIDList()) {
final ImagePlus imp = WindowManager.getImage(id);
if (imp == null) continue;
final ImageWindow win = imp.getWindow();
if (win != null) win.dispose();
}
// dispose all other ImageJ windows
for (final Window w : WindowManager.getAllNonImageWindows()) {
w.dispose();
}
}
});
But none of them work as one might hope. It cost me weeks of development and experimentation to make quitting work as we wanted in ImageJ2, according to the news posted linked above.
Here is some code using ImageJ2 that almost behaves the way you want:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;
import net.imagej.ImageJ;
public class IJDispose {
public static void main(final String... args) {
final ImageJ ij = new ImageJ();
ij.ui().showUI();
final JFrame frame = new JFrame("Hello");
final JButton b = new JButton("Close ImageJ");
b.addActionListener(new ActionListener() {
#Override
public void actionPerformed(final ActionEvent e) {
ij.getContext().dispose();
}
});
frame.getContentPane().add(b);
frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}
After launching it, press Shift+B to open the Blobs sample image. Then click the "Close ImageJ" button from the non-ImageJ frame. You'll see that the ImageJ main window and the image window dispose as desired (using this code from ImageJ Legacy).
However, there are (at least) three problems:
This example does not hook up the ij.getContext().dispose() call to the actual ImageJ1 UI window closing event. And doing that would not be trivial (I say without having dug deeply in this code recently).
After disposing ImageJ, as well as the extra JFrame, the JVM is supposed to shut down. We put a lot of effort into making it do so, actually. But it actually doesn't with the current version of ImageJ, presumably due to some undisposed resource(s) somewhere. This is a bug.
Clicking the X on the main ImageJ window shuts down the entire JVM, because ImageJ1's exitWhenQuitting flag gets set to true. You could toggle it back to false yourself, but this is actually tricky due to class loading issues relating to the fact that ImageJ2 patches ImageJ1 at runtime using Javassist.
The next question is: How badly do you really need this to work?

JFrame and JOptionPane are not clear

Whenever I execute JFrame of JOptionPane this is how its displayed. I have the latest version of eclipse and JDK. I use Windows 8. What might be the issue?!
public static void main(String args[]){
String disp="2.40894673";
JOptionPane.showMessageDialog(null, disp);
}
the problem occurs in all the codes. This is a sample code I wrote th problem occurs in this too.
Update your graphics and card drives.
If you're using Mac then as I found in this
page
look at:
Preferences > Fonts > Text antialiasing
If you're using Windows then from this
answer be sure it's checked:
Control Panel → Appearance and Personalization → Display → Adjust ClearType text
Then check your font settings for windows, menu items and dialog
boxes:
Control Panel → Appearance and Personalization → Personalization → Window Color → Advanced appearance settings
Most of times just step 1 solves the issue.
Try them and if worked let me know.
UPDATE
Try turning off ClearType from Control Panel as indicated in step 3,
as said in this answer
Also try deleting FNTCACHE.DAT from System32 as mentioned in
this other answer.
Also as said in this
forum
try to change your screen resolution, and also reducing Hardware acceleration.
Let me know if any of them solved the issue.
I've written a code for the same, and it works fine.
Program:
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class SDialog
{
public static void main(String[] args)
{
String disp="2.40894673";
// create a jframe
JFrame frame = new JFrame();
// show a joptionpane dialog using showMessageDialog
JOptionPane.showMessageDialog(frame,disp);
System.exit(0);
}
}

Why my Swing based GUI application is not responding?

I am trying to create my first GUI application using (Java + Eclipse + Swing). This is my code:
import java.awt.*;
import javax.swing.*;
public class HelloWorldSwing extends JFrame {
JTextArea m_resultArea = new JTextArea(6, 30);
//====================================================== constructor
public HelloWorldSwing() {
//... Set initial text, scrolling, and border.
m_resultArea.setText("Enter more text to see scrollbars");
JScrollPane scrollingArea = new JScrollPane(m_resultArea);
scrollingArea.setBorder(BorderFactory.createEmptyBorder(10,5,10,5));
// Get the content pane, set layout, add to center
Container content = this.getContentPane();
content.setLayout(new BorderLayout());
content.add(scrollingArea, BorderLayout.CENTER);
this.pack();
}
//============================================================= main
public static void main(String[] args) {
JFrame win = new HelloWorldSwing();
win.setTitle("TextAreaDemo");
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.setVisible(true);
}
}
The code was taken from here.
When I run the application from Eclipse the expected window appears (So, it's good. I see what I want to see). However, when I try to close the window or try to write something in the text area the program freezes. The OS writes me that program is not responding (I try it on Ubuntu).
Can anybody help me to find the reason of the problem?
Thank you in advance for any help.
I'm sure this doesn't have to do with the code, as others have found the code runs just fine on their machines - which points to a machine specific issue. From within Eclipse, make sure it is setup to use the expected JDK/JRE. However, before worrying about how Eclipse is handling your situation, I'd run things by hand first - especially since you've got a very simple class.
I would check to ensure that you're using the expected compiler and runtime. On Linux:
which javac
which java
If they're both what you expect, do the following:
javac HelloWorldSwing.java
java HelloWorldSwing
If you get a similar problem, then you know it's not the Eclipse configuration and it's something else. If you're not using the latest JDK, upgrade to the latest. If you're already at the latest, it could be a display driver. Do other JAVA swing programs work on this computer? I'm sure you could find some on the net, download an app already packaged as a jar and try running it.
did you try using the eventdispatcherthread to view the JFrame?
something like:
public static void main(String[] args){
SwingUtilities.invokeLater(new Runnable(){
public void run(){
createAndViewJFrame();
}
});
}
public void createAndViewJFrame(){
JFrame win = new HelloWorldSwing();
win.setTitle("TextAreaDemo");
win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
win.setVisible(true);
}
then your frame would be shown by the swing dispatcher thread.
hope it helped, although im just guessing...
Update: as commenters pointed you i f**ed up the invokeLater() call. I just edited this post to correct that. Thanx go to yishai & willcodejavaforfood for pointing it out!
frank
You need to catch the exit event and
respond with a System.exit( 0 );
You should be able to find that in
most swing examples online.
wrong stuff... sorry... coffee... argh....

Creating an offscreen frame in Java (or: how to avoid a blank menu on a Mac, when all application windows are closed)?

I am making a Mac application, and I want my menu bar to look right.
Any Mac user knows the menu bar should be in the top screen menu. Setting apple.laf.useScreenMenuBar to true in the property list file gets rid of the in-frame menu bars and moves the menu bar of the current focused window to the screen menu.
However, when all windows are hidden or when there are no windows, there are no menu bars to move to the top, and you just get a blank menu. I heard a solution to this was to create an offscreen window that is focused when no others are. The only purpose of it would be its menu, so that it could fill in when the others are gone.
However, I've been getting loads of problems. I can't seem to move the window off the screen because Macs won't let you set the coordinates to something past the size of the screen; it just cuts it off and positions it at the edge instead. Is there something else I have to do to make an offscreen window?
You should definitely consider WizardOfOdds' very helpful answer. Using "The Application Menu" correctly will help, and it's easy to set up a minimal Info.plist to get started. A persistent File menu will allow your application to open a new window when others are closed. This answer links to a simple example.
Although Apple's Human Interface Guidelines are an excellent guide to what your users will expect, you can certainly experiment with the approach you suggested in your question. In particular, you might try setLocation(Short.MIN_VALUE, Short.MIN_VALUE) on the invisible window. In addition, you might want to respond to a WindowEvent in some special way if it signals the close of the last visible window.
Addendum: When your listener sees the last visible window close, create a new, empty application window. Alternatively, move the invisible window onscreen and make it visible until the user decides how to proceed.
Addendum: Mac OS X helpfully prevents a visible window form being moved offscreen, but it's easy to put an invisible window in limbo, as shown below.
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;
public class FrameTest extends JFrame {
private static FrameTest marco;
private static FrameTest polo;
private static class MyPanel extends JPanel {
public MyPanel() {
super(true);
final JToggleButton b = new JToggleButton("Test");
b.addItemListener(new ItemListener() {
#Override
public void itemStateChanged(ItemEvent e) {
if (b.isSelected()) {
polo.setLocation(100, 100);
polo.setVisible(true);
}
else {
polo.setVisible(false);
polo.setLocation(Short.MIN_VALUE, Short.MIN_VALUE);
}
}
});
this.add(b);
}
}
public FrameTest(String title) {
super(title);
this.setLayout(new BorderLayout());
this.add(new MyPanel());
this.pack();
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(final String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
marco = new FrameTest("Marco");
marco.setLocationRelativeTo(null);
marco.setVisible(true);
polo = new FrameTest("Polo");
polo.setLocation(Short.MIN_VALUE, Short.MIN_VALUE);
}
});
}
}
I know that this post is quite old, anyway, I had the same problem and found the solution. Actually it's quite simple. Just don't add the JMenuBar to your main frame when running on mac os x, but to your application using
com.apple.eawt.Application.getApplication().setDefaultMenuBar(menuBar);
Now the MenuBar is still displayed even if you set all frame's visibility to false.
Not a direct solution, but I think some create a 1-pixel window instead. That yields complaints though, like one described at Super User: Chaotic behavior of a dead pixel on my iMac 24"...
First a note: your question seems really to be "How to have a Window menu following the Apple Human Interface Guidelines" and not "creating an offscreen frame in Java", which seems like a monstrous hack.
I suggest checking Apple's "Mac OS X Integration for Java", which, under "Window menu", shows apparently exactly what you're trying to achieve:
Apple Human Interface Guidelines suggests that all Mac OS X applications should provide a Window menu to keep track of all currently open windows. A Window menu should contain a list of windows, with a checkmark next to the active window.
This is a comment to trashgod's answer. It's too big so I have to move it here >.<
More problems!
I'm getting 2 errors:
line 23: The method itemStateChanged(ItemEvent) of type new ItemListener(){} must override a superclass method
line 50:The method run() of type new Runnable(){} must override a superclass method
Any help? I've never encountered this before. I don't know what it means.
EDIT: I have more problems! I need the offscreen window to be visible while it is offscreen for it to produce a menu to move to the screen menu bar. When I use the code
offScreen = new JFrame("WTF?! You can see me?");
offScreen.setSize(400,300);
offScreen.setLocation(0, java.awt.Toolkit.getDefaultToolkit().getScreenSize().height+50);
System.out.println(offScreen.getLocation());
offScreen.setVisible(true);
System.out.println(offScreen.getLocation());
I get the output:
java.awt.Point[x=0,y=1100]
java.awt.Point[x=0,y=961]
It moves it back once it's made visible again!
I've searched for ages and I can't find anything.
This code works in Java 7:
if( isMac ) {
//This creates an invisible frame so that we always have a menu bar visible
JFrame menuFrame = new JFrame();
menuFrame.setUndecorated( true );
menuFrame.setJMenuBar( defaultMenuBar );
AWTUtilities.setWindowOpaque( menuFrame, false );
menuFrame.setBounds( 0,0,1,1 );
menuFrame.setVisible( true );
}
Just call this before you open any other windows, and it will stay in the background and automatically become the focused window when others are closed. You can still use the com.apple.eawt.Application.getApplication().setDefaultMenuBar(menuBar) method in your application so that you don't need to call setJMenuBar() on each JFrame.

Window ID from Java SWT

I would like to find the window ID of my SWT program.
I start up my SWT shell in the standard way. How do I then find the ID of the window that's been created? The program is executing on Fedora 10 using the Compiz-Fusion window manager (if that makes a difference).
Code to help explain what I mean:
public static void main(String[] args) {
Display display = new Display();
Shell shell = new Shell();
// find window ID here??
shell.open();
while (!shell.isDisposed()) {
if(!display.readAndDispatch()) {
display.sleep();
}
}
}
Update 6 Mar 2009
After looking at and trying out a whole range of things (thanks to VonC for the suggestions below), I came across something that's worked so far. It's supremely dodgy but at least allows me to get on with some other work for the moment.
The ID returned from Control.embeddedHandle is close to the window ID. It's different by a predictable offset. So my code is:
public static void main(String[] args) {
...
Shell shell = new shell(display, SWT.NONE);
Composite e = new Composite(shell, SWT.EMBEDDED);
long windowID = e.embeddedHandle - WINDOW_ID_MAGIC_NUMBER;
e.dispose();
....
WINDOW_ID_MAGIC_NUMBER is 5+(number of widgets added to shell before the embedded composite).
It seems reliable on my system so far. I have yet to see if it falls over in a different environment.
If you create a Composite with the style SWT.EMBEDDED style, then under SWT/GTK+ Composite.embeddedHandle will be an X window ID you can use for parenting an XEMBED child.
Composite embed = new Composite(shell, SWT.EMBEDDED);
System.out.println ("X window ID: " + embed.embeddedHandle);
int hwndChild = OS.GetWindow ( c.handle, OS.GW_CHILD);
This supports embedding using the XEMBED protocol.
This is similar to the JNI code used to get the window ID from its handle
GtkWidget *widget = (GtkWidget *) handle;
GdkWindow *window = widget->window;
xwinid = GDK_WINDOW_XWINDOW(window);
Example of code here.
Example of class using OS:
org.eclipse.swt.widgets.Tree, org.eclipse.swt.widgets.CoolItem,
OS I can find is indeed org.eclipse.swt.internal.win32.OS, not gtk, and it is not a perfect solution because you would access an internal package, but that can give you an idea where to look.
In your case, org.eclipse.swt.internal.gtk.OS is the right class, and you should look in Tree or CoolItem sources how they are using the GetWindow function.
Some other function need to be called in GTK, like may be gtk_container_get_children(int container);
It is said in an answer to the message I was referring at the beginning
If you need the X window, there's no way to do this from the public SWT API (even going through internals), and furthermore even if there was a way I don't think you could guarantee it for all controls. I'm not sure if this works but the closest you could get might be to:
make Control.fixedHandle public
Use OS.GTK_WIDGET_WINDOW (control.fixedHandle) to get a GdkWindow
Use OS.gdk_x11_drawable_get_xid (gdkWindow) to translate that to an X window
I guess the other way might be to take Control.handle, and then call GTK_WIDGET_WINDOW() on it, or if that's null keep calling it on its parents until you find one with a GdkWindow, and then translate that to an X window.
The difficulty here is that SWT talks to GTK+, which talks to GDK, which then talks to X. So, there's three layers between you and the X window.
Not sure if this still matters to you, 7 years later :-), but this works for me:
private static long getWindowIdFromShell(Shell shell) {
long handle = shell.handle;
long topWidget = OS._gtk_widget_get_toplevel(handle);
long topWindow = OS._gtk_widget_get_window(topWidget);
long topXid = OS._gdk_x11_window_get_xid(topWindow);
return topXid;
}
In particular, the "get_toplevel" step is what jumps to the root widget/window, and so means you don't need the "minus magic window offset" hack (which I was initially stuck doing as well).

Categories