FontMetrics return garbage font descent - java

I am facing a weird problem in Eclipse, and even after lot of search, haven't found any Bugs also in this regard. My Problem is with the
handle field in FontMetrics Class. Since the API says its Platform Dependent, there is not much I can do about it. The problem is like this:
I have to export some diagrams, made of draw2d widgets and connections, to Word and PDF. Till now, the export feature was available as an Action to the toolbar of the Editor, in which Diagrams are drawn. It has been working fine. All I do is paint the FigureCanvas to an SWT Image, and save it to a File. There are APIs available with me, which then insert it to Word/PDF. Now, I need to that offline, i.e. without actually drawing the diagram on Screen. I did something like this to achieve this:
Job job = new Job("Making DFD for " + data.getName()) {
#SuppressWarnings("unchecked")
#Override
protected IStatus run(IProgressMonitor monitor) {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
Composite composite = new Composite(shell, SWT.NONE);
try {
imageFolder = new File(tempFolder + IOUtils.FILE_SEPARATOR +
"dfd-" + (new Date()).getTime());
composite.setLayout(new FillLayout());
final FigureCanvas canvas = new FigureCanvas(composite);
ArrayList<DFDFigureData> figureData = renderer.getDfdFigureDatas();
final DFDMaker3 dfdMaker;
dfdMaker = new DFDMaker3(canvas, "", figureData, null, false);
Logger.println("Shell Size:", shell.computeSize(-1, -1, true));
display.syncExec(new Runnable(){
public void run() {
dfdMaker.makeDFD();
shell.setSize(-1, -1);
dfdMaker.selectNode(-1, display);
}
});
Logger.println("Shell Size:", shell.computeSize(-1, -1, true));
/* Image Export Stuff Goes here */
return Status.OK_STATUS;
} catch (Exception e) {
Logger.println("Error in DFD Creation Job", e.toString());
return Status.CANCEL_STATUS;
} finally {
composite.dispose();
shell.dispose();
display.dispose();
}
}
};
job.setPriority(Job.SHORT);
job.schedule();
When I run this for the first time, both the Log statements tell me a good story:
Shell Size::: Point {72, 98}
Shell Size::: Point {1216, 524}
But when I run the same code 2nd time, without closing the application, I get:
Shell Size::: Point {72, 98}
Shell Size::: Point {1216, 1945541082}
The large Height value of the shell spoils everything. After intense debugging, I found that the second time, a FlowPage, that I am using, get a wrong value for Font's descent. The method FontMetrics.getDescent() returns a Random large value.
I am not sure how exactly to proceed in this. I've disposed all the resources that I used the first time. The Display, Shell, Composite, Canvas, and even the GC and SWTGraphics. Can anyone tell me if its a bug? If not, any idea how can I find the problem here?

Related

How to input data into external GUI using Java runtime exec

I am trying to write java code to access and use the DullRazor software.
Please refer to this image of the DullRazor application:
I had an idea of creating a Java runtime program that could loop through all images I need to process(the software only allows 1 image at a time) and complete the necessary steps required for the DullRazor software to successfully alter an image for every image I have.
The DullRazor software works as follows:
-Source File: Requires the path to an image(jpg in my case) to be altered i.e c://Isic-Images//image0000.jpg.
-Target File: Requires the location for the new image with a new image name i.e c://finalLocation//newImage.jpg
-Start: Run the program after giving the inputs in the correct format as described above.
My thinking is iterating through all my images, creating new ones and incrementing the name(img00, img001 etc..).
I have never attempted anything like this in Java and I have had some trouble accessing the Input fields of the software as well as the application's start button.
The code below is just very basic for opening the application, but I am unsure how to access the various items in the DullRazor application and being able to input Strings in those aforementioned fields(again, refer to the DullRazor picture).
private String trainingPath = "C:\\Users\\user\\AppData\\Local\\Temp\\ISIC-Images\\Training\\0";
private String finalPath = "C:\\Users\\user\\finalLocation\\";
public static void main(String[] args) {
try {
Runtime runTime = Runtime.getRuntime();
Process process = runTime.exec("C:\\Users\\user\\Desktop\\dullrazor.exe");
System.out.println("Opening DullRazor");
OutputStream output = process.getOutputStream();
InputStream input = process.getInputStream();
Thread.sleep(2000);
process.destroy();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException s) {
s.printStackTrace();
} finally {
System.out.println("Closing Dullrazor");
}
}
I have just been testing a bit with the code above, but I am unsure on how to proceed.
Tell me if there is anything that needs clarifying.
Any help is greatly appreciated, thanks.
You can use Java's java.awt.Robot class to control mouse and keyboard on the screen.
This is a simple example entering "test1" and "test2" into two input fields:
Robot r = new Robot();
r.mouseMove(22, 125);
r.mousePress(InputEvent.BUTTON1_DOWN_MASK);
r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
r.keyPress('T');
r.keyRelease('T');
r.keyPress('E');
r.keyRelease('E');
r.keyPress('S');
r.keyRelease('S');
r.keyPress('T');
r.keyRelease('T');
r.keyPress('1');
r.keyRelease('1');
r.mouseMove(200, 125);
r.mousePress(InputEvent.BUTTON1_DOWN_MASK);
r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
r.keyPress('T');
r.keyRelease('T');
r.keyPress('E');
r.keyRelease('E');
r.keyPress('S');
r.keyRelease('S');
r.keyPress('T');
r.keyRelease('T');
r.keyPress('2');
r.keyRelease('2');
The above code in action:
If the position of the new application window does not change with each start, and the tool is not about to be deployed to users, this might already suffice. However, if it changes the position with each start, the challenge is to find the window position to add the relative input element positions from there. There are Windows (platform) specific approaches facilitating the Win32 API through JNA, though I'm not familiar with it and whether it is still available in current Microsoft Windows versions.
See these related questions on determining other windows positions:
Windows: how to get a list of all visible windows?
How to get the x and y of a program window in Java?
Using robot works perfectly in order to input into the targeted fields and clicking start/clear button on the application.
In order to find the x & y positions of the application I used runtime exec to open dullrazor and then take a screenshot of the screen with the application up where mouse clicks reveals the x and y position of the current click. Below is the code for finding x & y which I found at this Stackoverflow thread:
Robot robot = new Robot();
final Dimension screenSize = Toolkit.getDefaultToolkit().
getScreenSize();
final BufferedImage screen = robot.createScreenCapture(
new Rectangle(screenSize));
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JLabel screenLabel = new JLabel(new ImageIcon(screen));
JScrollPane screenScroll = new JScrollPane(screenLabel);
screenScroll.setPreferredSize(new Dimension(
(int)(screenSize.getWidth()/2),
(int)(screenSize.getHeight()/2)));
final Point pointOfInterest = new Point();
JPanel panel = new JPanel(new BorderLayout());
panel.add(screenScroll, BorderLayout.CENTER);
final JLabel pointLabel = new JLabel(
"Click on any point in the screen shot!");
panel.add(pointLabel, BorderLayout.SOUTH);
screenLabel.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent me) {
pointOfInterest.setLocation(me.getPoint());
pointLabel.setText(
"Point: " +
pointOfInterest.getX() +
"x" +
pointOfInterest.getY());
}
});
JOptionPane.showMessageDialog(null, panel);
System.out.println("Point of interest: " + pointOfInterest);
}
});
Thank you try-catch-finally for a great answer.

Selenium WebDriver : Verify Print Window dialog displayed on the page

I have a scenario to verify Print Properties dialog (Windows component) opening up correctly after clicking on Print link. Aware of Robot utility class in Java which can emulate keyboard events like Escape/Enter etc. to operate on that window.
Is there any way we can verify the new dialog opened up is a Print dialog - something to verify dialog title i.e. Print or retrieve text from that windows dialog or something else which will confirm dialog to be a Print dialog.
The print dialog comes from the os, which selenium can't handle (yet). Therefore you won't be able to check for existence. The only way to I can think of is using a java.awt.Robot, send VK_ESCAPE and assert that the test continues.
As a starter you could try out this:
Runnable r = new Runnable() {
#Override
public void run() {
try {
Robot r = new Robot();
r.delay(1000);
r.keyPress(KeyEvent.VK_ESCAPE);
r.keyRelease(KeyEvent.VK_ESCAPE);
} catch (Exception ex) {
ex.printStackTrace();
}
}
};
Actions actions = new Actions(getDriver());
actions.sendKeys(Keys.CONTROL).sendKeys("p");
Thread t = new Thread(r);
t.start();
actions.perform();
//some stupid asserts that we reached here
If you are operating in windows (which I am going to assume you are) you can use the inspect.exe tool that comes along with visual studio. It will allow you to interact with the dialogue box and even send any information that you want accurately including selecting elements from the drop down or any other interaction needed. This even works if you wish to save files using selenium, but to answer your question, you can even use it to detect if that window is indeed there. How you want to proceed from there is your call.
//using System.Windows.Automation;
//using System.Windows.Forms;
AutomationElement desktop = AutomationElement.RootElement;
AutomationElement Firefox = desktop.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.ClassNameProperty, "MozillaWindowClass"));
AutomationElement PrinterComboBox = PrintForm1.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.AutomationIdProperty, "1139"));
SelectionPattern selectPrinterComboBox = (SelectionPattern)PrinterComboBox.GetCurrentPattern(SelectionPattern.Pattern);
AutomationElement ItemInDropdown = PrinterComboBox.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "SelectPrintMethod"));
SelectionItemPattern ItemInDropdownSelectItem = (SelectionItemPattern)ItemInDropdown.GetCurrentPattern(SelectionItemPattern.Pattern);
ItemInDropdownSelectItem.Select();
AutomationElement OKButton = PrintForm1.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.AutomationIdProperty, "1"));
InvokePattern ClickOK = (InvokePattern)OKButton.GetCurrentPattern(InvokePattern.Pattern);
ClickOK.Invoke();

Redirecting real-time SSH Console Output to JFrame

I'm calling plink to execute a a shell script at a remote location using ssh from Java. While I get the buffered data back from the ssh console, I want to write them to a JTextField etc in real time (the backend code executes for about 10 minutes and keeps generating some strings).
While doing that, the execution hangs up till the backend code is completely executed and displays output all at once. If I do it to direct Eclipse console, it writes line by line while executing. Any suggestions?
//JFrame Component
public GUIApplicationConsoleFrame(String title) {
dispFrame = new JFrame(title);
opArea = new JTextArea("");
ipField = new JTextField();
// Writing Output, redirected to JTextArea
if (std.available () > 0) {
value = std.read ();
out((char) value);
while (true) {
value = std.read ();
out((char) value);
if (<terminating condition>)
if (++count==2)
break;
Thread.sleep(3);
}
}
Thanks,
Arya
You should put ssh in a background thread and update the JTextArea from it. That way you will not block the event dispatch thread and it will be able to update graphical interface even if the background (worker) thread is not terminated.

Correct using VLCj

I try to use VLCj to get access to web-cameras. I am using this code:
public static void main(String[] args) {
// Create player.
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory();
DirectMediaPlayer mediaPlayer = mediaPlayerFactory.newDirectMediaPlayer(
320, 240,
new RenderCallback() {
#Override
public void display(Memory arg0) {
// Do nothing.
}
});
// Options setup.
String[] options = new String[]{};
String mrl = "v4l2:///dev/video0"; // Linux
// Start preocessing.
mediaPlayer.startMedia(mrl, options);
BufferedImage bufImg;
for (int i = 0; i < 1000; ++i) {
bufImg = mediaPlayer.getSnapshot();
// Do something with BufferedImage...
// ...
}
// Stop precessing.
mediaPlayer.stop();
mediaPlayer = null;
System.out.println("Finish!");
}
And this code partially works -- I can get and work with BufferedImage, but:
I got an error in to output: [0x7f0a4c001268] main vout display error: Failed to set on top
When main loop is finished and camera was disabled program don't finished! I see Finish! message, but program not return control into IDE or console.
UPD:
I am using openSUSE 12.2 x64, VLC 2.0.3 installed and working properly for all video files, library VLCj 2.1.0.
This code working properly:
public static void main(String[] args) {
// Configure player factory.
String[] VLC_ARGS = {
"--intf", "dummy", // no interface
"--vout", "dummy", // we don't want video (output)
"--no-audio", // we don't want audio (decoding)
"--no-video-title-show", // nor the filename displayed
"--no-stats", // no stats
"--no-sub-autodetect-file", // we don't want subtitles
"--no-inhibit", // we don't want interfaces
"--no-disable-screensaver", // we don't want interfaces
"--no-snapshot-preview", // no blending in dummy vout
};
MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory(VLC_ARGS);
// Create player.
HeadlessMediaPlayer mediaPlayer = mediaPlayerFactory.newHeadlessMediaPlayer();
// Select input device.
String mrl = "v4l2:///dev/video0"; // Linux
// Start processing.
mediaPlayer.startMedia(mrl);
BufferedImage bufImg;
for (int i = 0; i < 1000; ++i) {
bufImg = mediaPlayer.getSnapshot();
// Do something with BufferedImage...
// ...
}
// Stop processing.
mediaPlayer.stop();
// Finish program.
mediaPlayer.release();
mediaPlayerFactory.release();
}
Re your native window: VLCj opens a shared instance to the VLC library.
A headless media palyer is NOT intended to have a video or audio output!
In fact, if you need anything to play (and not to stream to anywhere else) you need to create either an output window or use a direct media player (may be much more complicated)
So, if a headless player needs to play something it opens a native window to perform the playback!
Source: http://www.capricasoftware.co.uk/wiki/index.php?title=Vlcj_Media_Players
Re the error: the video display component MUST be the top component of the panel, window or whereever it is added to. Otherwise it will throw the error
main vout display error: Failed to set on top
Furthermore, if you put anything over the component it will destroy the video output which won't work anymore!
Anyway, I don't know how the DirectMediaPlayer works in detail but VLCj has some weird behaviour... Maybe getSnapshot() needs a video display component but I'm not sure.
Re your not finishing program: you join to finish your own thread. This can't work because your thread "sleeps" until the other thread who is waited for has been terminated but as this is your own thread it "sleeps" and won't terminate.
You can test this behaviour with this short code in a main method:
System.out.println("Test start");
Thread.currentThread().join();
System.out.println("Test stop");
You will NEVER reach the "Test stop" statement.

How to change the default font size in the Swing GTK LookAndFeel?

Is there a way to change the default font size in the Swing GTK LaF?
The GTK LaF seems to assume 72dpi, so all the fonts are only 3/4 of the size they should be when using a 96dpi screen. See this Fedora bug for details. I'd like to find a workaround in the meantime, while I wait for the fix.
I've already tried resetting the font size via UIDefaults, as recommended here, for example, but (as also noted there) the GTK LaF appears to ignore this.
I could build a widget factory that would also set the desired font size for creating all of my Swing widgets, but that's going to be massively invasive, so I'd like to avoid that route if there's any other way.
Edit: The following doesn't work:
public class GTKLaF extends com.sun.java.swing.plaf.gtk.GTKLookAndFeel {
#Override
public UIDefaults getDefaults() {
final float scale = 3f;
final UIDefaults defaults = super.getDefaults();
final Map<Object,Object> changes = new HashMap<Object,Object>();
for (Map.Entry<Object,Object> e : defaults.entrySet()) {
final Object key = e.getKey();
final Object val = e.getValue();
if (val instanceof FontUIResource) {
final FontUIResource ores = (FontUIResource) val;
final FontUIResource nres =
new FontUIResource(ores.deriveFont(ores.getSize2D()*scale));
changes.put(key, nres);
System.out.println(key + " = " + nres);
}
else if (val instanceof Font) {
final Font ofont = (Font) val;
final Font nfont = ofont.deriveFont(ofont.getSize2D()*scale);
changes.put(key, nfont);
System.out.println(key + " = " + nfont);
}
}
defaults.putAll(changes);
return defaults;
}
}
You might think this would print at least a dozen key-value pairs, but it prints only one: TitledBorder.font. Apparently the other font properties are not supplied by the GTLLookAndFeel, but come from someplace else!
My suggestion is to create your own subclass of GTKLookAndFeel and use that.
In your subclass, I'd probably override getDefaults(). In your getDefaults() you can get the UIDefaults that GTKLookAndFeel was going to return and adjust them if necessary. (By wrapping or subclassing them and overriding the UIDefaults.getFont methods.)
Get the current DPI with
int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
and if it's not 72 you can change the font size accordingly.
Edit: the link you posted doesn't work, I believe because GTKLookAndFeel overrides the methods involved and doesn't let any defaults from its ancestors to pass through. Overriding it in turn should allow you to circumvent that problem.
There appears to be no way to set the default font size. However, the bug referenced in the question has since been fixed, so the need to do this is now moot.
There is something wrong with the code you linked.UIDefaults.get(key) function doesnt have to return a Font instance. It may be a javax.swing.plaf.FontUIResource instance.
Following code snippet finds all installed look and feels, than changes all fonts sizes at a ratio of scale
float scale=1.1f;
UIManager.LookAndFeelInfo looks[] = UIManager.getInstalledLookAndFeels();
for (UIManager.LookAndFeelInfo info : looks) {
//if you want to change LaF to a spesific LaF,such as "GTK"
//put here a if statement like:
//if(info.getClassName().contains("GTK"))
UIManager.setLookAndFeel(info.getClassName());
UIDefaults defaults = UIManager.getDefaults();
Enumeration newKeys = defaults.keys();
while (newKeys.hasMoreElements()) {
Object obj = newKeys.nextElement();
Object current = UIManager.get(obj);
if (current instanceof FontUIResource) {
FontUIResource resource = (FontUIResource) current;
defaults.put(obj, new FontUIResource(resource.deriveFont(resource.getSize2D()*scale)));
// System.out.printf("%50s : %s\n", obj, UIManager.get(obj));
} else if (current instanceof Font) {
Font resource = (Font) current;
defaults.put(obj, resource.deriveFont(resource.getSize2D()*scale));
// System.out.printf("%50s : %s\n", obj, UIManager.get(obj));
}
}
}
I find something about the GTK LaF problem a book, Java Examples in a Nutshell, Third Edition.
Take a look at it here
I lost a lot of time figuring out how to make our app decent on ubuntu and I came to this hack.
I have tried like someone suggested to extend GTKLookAndFeel but since it uses many native calls to GTKEngine and I realized it was not viable.
I hope this helps
Just after setting the look and feel call my hack checkGTKLookAndFeel() it reduces the font standard of two points :
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
try {
InvoicexUtil.checkGTKLookAndFeel();
} catch (Exception e) {
e.printStackTrace();
}
public static void checkGTKLookAndFeel() throws Exception {
LookAndFeel look = UIManager.getLookAndFeel();
if (!look.getID().equals("GTK")) return;
new JFrame();
new JButton();
new JComboBox();
new JRadioButton();
new JCheckBox();
new JTextArea();
new JTextField();
new JTable();
new JToggleButton();
new JSpinner();
new JSlider();
new JTabbedPane();
new JMenu();
new JMenuBar();
new JMenuItem();
Object styleFactory;
Field styleFactoryField = look.getClass().getDeclaredField("styleFactory");
styleFactoryField.setAccessible(true);
styleFactory = styleFactoryField.get(look);
Field defaultFontField = styleFactory.getClass().getDeclaredField("defaultFont");
defaultFontField.setAccessible(true);
Font defaultFont = (Font) defaultFontField.get(styleFactory);
FontUIResource newFontUI;
newFontUI = new FontUIResource(defaultFont.deriveFont((float)(defaultFont.getSize() - 2f)));
defaultFontField.set(styleFactory, newFontUI);
Field stylesCacheField = styleFactory.getClass().getDeclaredField("stylesCache");
stylesCacheField.setAccessible(true);
Object stylesCache = stylesCacheField.get(styleFactory);
Map stylesMap = (Map) stylesCache;
for (Object mo : stylesMap.values()) {
Field f = mo.getClass().getDeclaredField("font");
f.setAccessible(true);
Font fo = (Font)f.get(mo);
f.set(mo, fo.deriveFont((float)(fo.getSize() - 2f)));
}
}
call the various swing components constructor to initialize GTK styles.
not very elegant but it works

Categories