Cannot load ImageIcon in JLabel - Java, Swing - java

I have a question that has been boring me for some days.
I'm implementing some swing interfaces that is supposed to load an image:
When i press a button it triggers an event that calls the following method:
private void GetDataPanelGeral()
{
ArrayList<String> Files = new ArrayList<>();
java.util.Date selectedDate = (java.util.Date) this.JDatePickerImpl_GERAL_MUDANÇAS_datePicker_START.getModel().getValue();
java.sql.Date sqlDateINICIO = new java.sql.Date(selectedDate.getTime());
selectedDate = (java.util.Date) this.JDatePickerImpl_GERAL_MUDANÇAS_datePicker_END.getModel().getValue();
java.sql.Date sqlDateFIM = new java.sql.Date(selectedDate.getTime());
//CALL MODULE 5
RunningLoop loop = null;
Thread t = new Thread
(
loop = new RunningLoop(50000,this.StringDBName,this.StringDBDriver,
this.StringDBUser,this.StringDBPass,this.PathToData,
sqlDateINICIO.toString(),
sqlDateFIM.toString(),
true)
);
t.start();
loop.StopLooping();
this.ImageLabelGERALMUNDANCAS.revalidate();
this.ImageLabelGERALMUNDANCAS.repaint();
this.ImageLabelGERALMUNDANCAS = new JLabel(new ImageIcon("this.PathToData+"/Results/Outputs/P5/0.png",""));
this.ImageLabelGERALMUNDANCAS.repaint();
JPanel Aggregator = new JPanel();
Aggregator.add(this.ImageLabelGERALMUNDANCAS);
Aggregator.setBackground(this.color);
//this.Aggregatorr.add(this.ImageLabelGERALMUNDANCAS);
this.JPanel_TABGeral.remove(1);
this.JPanel_TABGeral.add(Aggregator,1);
this.JPanel_TABGeral.revalidate();
this.JPanel_TABGeral.repaint();
Aggregator.revalidate();
Aggregator.repaint();
}
the image loaded in the line this.ImageLabelGERALMUNDANCAS = new JLabel(new ImageIcon("this.PathToData+"/Results/Outputs/P5/0.png","")); is created by a module called in the lines
//CALL MODULE 5
RunningLoop loop = null;
Thread t = new Thread
(
loop = new RunningLoop(50000,this.StringDBName,this.StringDBDriver,
this.StringDBUser,this.StringDBPass,this.PathToData,
sqlDateINICIO.toString(),
sqlDateFIM.toString(),
true)
);
t.start();
loop.StopLooping();
it seems to be all ok but it does not load the image.. If i try to load another image it works perfectly so i think the problem is the creation of the image in the thread.
Can somebody help me?
Ps: I'm still need to work in some code, currently i'm trying everything to get this work, then i'll worry about better code
Kind regards

Related

Lanterna- how do you create a simple CheckBox menu?

So far I have
Terminal terminal = new DefaultTerminalFactory().createTerminal();
TerminalScreen screen = new TerminalScreen(terminal);
MultiWindowTextGUI mwtg = new MultiWindowTextGUI​(screen);
CheckBoxList checkBoxList = new CheckBoxList<String>();
checkBoxList.addItem("Check one");
checkBoxList.addItem("Check two");
What I can't figure out is how to add checkBoxList directly to mwtg
Many thanks for your help
ok, so after muddling blindly through the API for hours guessing here and there, I did this, which works but is probably clunky or smells, so please feel free to improve on my own answer.
private MultiWindowTextGUI mwtg;
private BasicWindow bw;
private CheckBoxList<String> checkBoxList;
private List<String> ckeckedItems;
Terminal terminal = new DefaultTerminalFactory().createTerminal();
TerminalScreen screen = new TerminalScreen(terminal);
MultiWindowTextGUI mwtg = new MultiWindowTextGUI​(screen);
this.checkBoxList = new CheckBoxList<String>();
this.checkBoxList.addItem("item1");
this.checkBoxList.addItem("item2");
this.checkBoxList.addItem("item3");
this.checkBoxList.addListener((sel, prev) ->
{ this.ckeckedItems = this.checkBoxList.getCheckedItems​(); }
);
Panel panel = new Panel();
panel.setLayoutManager(new GridLayout(4));
panel.addComponent(this.checkBoxList);
Button button = new Button("Done", () -> this.bw.close());
button.addTo​(panel);
this.bw = new BasicWindow("Choices");
this.bw.setComponent(panel);
this.mwtg.addWindowAndWait(this.bw);
I hope this may be useful for someone...

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.

Error when using Double.parseDouble

Im new to java and just wondering how do i get rid of this error:
Exception in thread "main" java.lang.NumberFormatException: empty String
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1011)
at java.lang.Double.parseDouble(Double.java:540)
at fksdfs.test1.assign(test1.java:69)
at fksdfs.test1.main(test1.java:60)
I'm trying to get the Value from the textfield and convert it into a double to perform calculations on but it is not working. Can anyone help me?
Sorry for the messy coding.
public class test1 {
private JTextField tField;
public static void main(String[] args) {
JLabel Age = new JLabel("Age");
JTextField textField = new JTextField(10);
JLabel Overall = new JLabel("Overall: ");
JTextField age = new JTextField(10);
JLabel shoot = new JLabel("Shooting: ");
JTextField shooting = new JTextField(10);
JLabel dribble = new JLabel("Dribbling: ");
JTextField dribbling = new JTextField(10);
JLabel pass = new JLabel("Passing : ");
JTextField passing = new JTextField(10);
JLabel defend = new JLabel("defending : ");
JTextField defending = new JTextField(10);
JLabel head = new JLabel("Heading : ");
JTextField heading = new JTextField(10);
JLabel pace = new JLabel("Pace: ");
JTextField pacey = new JTextField(10);
JPanel panel = new JPanel();
panel.add(Age);
panel.add(textField);
panel.add(Overall);
panel.add(age);
panel.add(shoot);
panel.add(shooting);
panel.add(dribble);
panel.add(dribbling);
panel.add(pass);
panel.add(passing);
panel.add(defend);
panel.add(defending);
panel.add(head);
panel.add(heading);
panel.add(pace);
panel.add(pacey);
String age1 = textField.getText();
String overall1 = age.getText();
String shooting1 = shooting.getText();
String dribbling1 = dribbling.getText();
String passing1 = passing.getText();
String heading1 = heading.getText();
String defending1 = defending.getText();
String pace1 = pacey.getText();
JOptionPane.showMessageDialog(null, panel);
}
public static void assign(String s) {
Double.parseDouble(s);
}
}
The code that is causing your error is not shown in your code above. It is where you call the assign method. When you are calling it, the String is empty, and so you're trying to convert "" into a number which makes sense should throw this exception.
Note the exception message is telling you all this:
Exception in thread "main" java.lang.NumberFormatException: empty String:
The String is empty -- no number in it.
at fksdfs.test1.assign(test1.java:69)
It's occurring at line 69 of test1.java where you all assign.
The fix: don't do this, don't try to parse an empty String. Test if the String is empty first, or do your parsing in a try/catch block.
As an aside, please put in the effort to post well formatted code when asking questions here. We're volunteers and as such expect you to do put in the effort so that it isn't unduly hard to read and understand your code if you're asking us for help. Also, avoid doing all this stuff in the main method or using static methods such as your assign method. This method should be an instance method, and most all of your code should be in a proper OOP class. You will want to learn how to create classes and basics of Java before trying to create complex GUI's, and the Java Tutorials can help.
Just as a tip for your future code...
When using GUIs and inputing code it is often better to create a pre-made exception handler for incorrect inputs. My preference would be:
try{
double somethingDouble = Double.parseDouble(something.getText());
}catch(){
JOptionPane.showMessageDialog(frame,
"Check input - this is supposed to be a decimal value!");
something.setText("");
e.printStackTrace();
}
that way you could just add the try block into an actionPerformed method and determine if the user of your product - or in this case, your code - could determine if he/she entered in valid input.
Note: place the e.printStackTrace() line after the error message in the try block

Populating a JTable with parsed information

I am trying to populate a JTable with information taken from a website (namely price and item name). I have a class that asks the user to input a URL and scans the page for the price and item name as well as the URL. Currently it takes all the parsed information and stores it in three different text files, one for price, one for item name, and one for the URL. I am trying to populate a JTable containing three columns (item name, price, and URL) with this information but every time I scan a new page the text files are overwritten and the previous information is lost. I don't necessarily need the JTable to be populated via the text file, I just need it to somehow get the information. Here is some of my code.
public BestBuy (JFrame frame){
super (frame, "Best Buy URL", true);
setLayout (new FlowLayout());
label = new JLabel ("Enter Best Buy URL");
add (label);
url = new JTextField ("Enter URL Here", 40);
add (url);
submit = new JButton ("Submit");
add (submit);
event b = new event ();
submit.addActionListener (b);
}
public class event implements ActionListener{
public void actionPerformed (ActionEvent b){
try {
String datab = url.getText(); //perform your operation
datab = datab.trim();
datab = datab.toLowerCase();
Document document = Jsoup.connect(datab).get();
String amountb = document.select(".amount").first().text();
String nameb = document.select(".product-title").first().text();
FileWriter stream = new FileWriter ("C:\\Users\\Daniel\\Desktop\\price.txt");
BufferedWriter out = new BufferedWriter (stream);
out.write(amountb + "\n");
out.newLine();
out.close();
FileWriter stream1 = new FileWriter ("C:\\Users\\Daniel\\Desktop\\itemName.txt");
BufferedWriter out1 = new BufferedWriter (stream1);
out1.write(nameb + "\n");
out1.newLine();
out1.close();
FileWriter stream2 = new FileWriter ("C:\\Users\\Daniel\\Desktop\\url.txt");
BufferedWriter out2 = new BufferedWriter (stream2);
out2.write(datab + "\n");
out2.newLine();
out2.close();
}
catch (Exception ex) {
}
setVisible (false);
}
This class asks the user for a Best Buy URL and parses the given page for item name, and price then writes it to files on my desktop.
public FirstGui (){
setLayout (new FlowLayout ());
String[] columnName = {"Item Name", "Price", "URL"};
Object [] [] data = {
};
table = new JTable (data, columnName);
table.setPreferredScrollableViewportSize(new Dimension (500, 300));
table.setFillsViewportHeight (true);
JScrollPane scrollpane = new JScrollPane (table);
add (scrollpane);
Now I am trying to get that parsed information onto my JTable but I have no idea how to do so. I tried to do
public getdatab() {
return datab;
}
public getnameb() {
return nameb;
}
public getamountb() {
return amountb;
}
but all these strings are within a void so that did not work. As you can probably see I am quite new to java and this might have an obvious solution but I have been stuck on this for a few days and cant figure it out. Thank you.
I'm not sure exactly how your getting your data, but you want to do something like this. Since you're trying to write the data to three different files, I will assume the data is coming in from three different streams. Here's the thing though. For this to work, all the data needs to be in parallel, Meaning that the first item, should correspond to the first price and first url, and so on. If this is the case, you can do something like this.
Have three separate lists.
List<String> names = new ArrayList<String>();
List<String> prices = new ArrayList<String>();
List<String> urls = new ArrayList<String>();
Then for each item you were going to add to a file, add to the list instead.
Use a DefaultTableModel as the model of your JTable
String[] columnName = {"Item Name", "Price", "URL"};
DefaultTableModel model = new DefaultTableModel(columnNames, 0);
table = new JTable(model);
Now you can just add rows, using the data from the lists. Use the method model.addRow(row), where row is an array of Objects
for (int i = 0; i < names.size(); i++) {
String name = names.get(i);
String price = prices.get(i);
String url = urls.get(i);
model.addRow(new Object[] { name, price, url });
}
That's all there is to it. The model will update the table for you dynamically. But remember, like I said, the data in the lists must be in sync with one another for you to get the desired result.
If you're getting data in one row at a time, instead of one column at a time, that makes it even easier. For each set of data, that comes in, just add it as a row like it did in step 5.

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