When I try to add anything to JFrame in constructor and I have IllegalArgumentException.
Similar code is working in documentation:
https://docs.oracle.com/javase/tutorial/uiswing/layout/none.html
Why my very simple code doesn't work? It is created in Netbeans 10.
Edit:
I also tried add label with position and sieze (setBounds) it doesn't help. I changed the code with setBounds method.
First, main class in JavaTestApp.java:
package javatestapp;
public class JavaTestApp {
public static void main(String[] args) {
TestForm mainFrame = new TestForm();
mainFrame.setLocation(300, 150);
mainFrame.setVisible(true);
mainFrame.toFront();
mainFrame.repaint();
}
}
Second file is:
package javatestapp;
import javax.swing.JLabel;
public class TestForm extends javax.swing.JFrame {
/**
* Creates new form TestForm
*/
public TestForm() {
initComponents();
JLabel label = new JLabel("Test label");
label.setBounds(10,10,100,25);
getContentPane().add(label);
}
// GENERATED CODE BELOW
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
pack();
}// </editor-fold>
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(TestForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(TestForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(TestForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(TestForm.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the form */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new TestForm().setVisible(true);
}
});
}
Stacktrace, regarding to #VGR request:
Exception in thread "main" java.lang.IllegalArgumentException
at org.netbeans.lib.awtextra.AbsoluteLayout.addLayoutComponent(Unknown Source)
at java.awt.Container.addImpl(Container.java:1120)
at java.awt.Container.add(Container.java:410)
at javatestapp.TestForm.<init>(TestForm.java:16)
at javatestapp.JavaTestApp.main(JavaTestApp.java:5)
BUILD STOPPED (total time: 9 seconds)
Link to project uploaded on weetransfer:
Project (scanned via my Bitdefender antivir)
I also chosen absolute layout
And that is your problem. You are not using it correctly.
getContentPane().add(label);
You can't just add the label to the frame without specifying the proper constraints. I've never used AbsoluteLayout (because I believe in proper layout management) but I would guess you need to specify constraints like x, y, width, height.
The layout manager can't guess where you want to position the component so you need to specify all the information. That is why you should be using a layout manager. Then the layout manager will position the component based on the rules of the layout manager. Much easier, once you practice it a little.
Related
What I want is entirely WindowsLookAndFeel, and I have this code in my JFrame.
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (Exception ex) {
ex.printStackTrace();
}
However, what I got it part Windows, part Metal (the cross platform style which looks awful. I think I know where the problem is:
The abnormal part(metal part) is a JPanel, and it is not originally built in the JFrame. I have a button. If pressed, the JPanel will be added to the JFrame.
if (((JToggleButton) e.getSource()).isSelected()) {
getContentPane().add(Console.getInstance(), BorderLayout.EAST);
} else {
remove(Console.getInstance());
}
revalidate();
pack();
But still, I don't know why this happens, and how to solve it.
You need to define the look and feel outside of the EDT. Create a class having a main method. In that method set the LAF and then display the app:
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch(Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
jFrame.pack();
jFrame.setVisible(true);
}
});
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(MyDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the dialog */
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
MyDialog dialog = new MyDialog(new javax.swing.JFrame(), true);
dialog.addWindowListener(new java.awt.event.WindowAdapter() {
#Override
public void windowClosing(java.awt.event.WindowEvent e) {
System.exit(0);
}
});
dialog.setVisible(true);
}
});
}
The MyDialog class just has few combos and textfields and am populating combo with DB values. On selecting one combo value i fetch another value from DB to populate the next combo.
The above program runs the same way without using invokeLater threading. When does invokeLater becomes useful in Swing programming. I have read some about it, but all seems to be theoratical. What difference does the invokeLater makes to the application? Is it enough to use it just inside main method or it should also be used in action Listeners?
SwingUtilities.invokeLater and java.awt.EventQueue.invokeLater - are they same?
Nothing theoretical about it. It's very practical. The SwingUtilities.invokeLater() method guarantees that the code within the Runnable will run on the Event Dispatch Thread (EDT). This is important because Swing is not thread-safe, thus anything related to the GUI (Swing, etc.) needs to run on the EDT. The EDT is a "it happens whenever it happens" thread that makes no guarantees about the order in which things are executed. If the GUI code is executed within a background thread (say, within a SwingWorker instance), then it can throw errors. I learned this the hard way: in my learning years, executing GUI-changing code within a background thread caused random, inconsistent RuntimeExceptions that I couldn't figure out. It was a good learning experience (SwingWorker has a doInBackground() method for background tasks and a done() method for EDT tasks).
In the same way you don't want to execute GUI code on a background thread, you also don't want to execute large operations (database queries, etc) on the EDT. This is because the EDT is dispatching all of the GUI events so everything on the EDT should be very short and sweet. You can easily see this with a JProgressBar set to indeterminate.
This SSCCE should illustrate it nicely. Notice the motion of the JProgressBar as method() is called, once on a background thread and once on a EDT thread.
import javax.swing.JFrame;
import javax.swing.JProgressBar;
import javax.swing.SwingWorker;
/**
*
* #author Ryan
*/
public class Test {
public static void main(String args[]) {
JFrame frame = new JFrame();
JProgressBar jpb = new JProgressBar();
jpb.setIndeterminate(true);
frame.add(jpb);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
new Task().execute();
}
public static void method() { // This is a method that does a time-consuming task.
for(int i = 1; i <= 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i);
}
}
static class Task extends SwingWorker<Void, Void> {
#Override
protected Void doInBackground() throws Exception {
/* Executing method on background thread.
* The loading bar should keep moving because, although method() is time consuming, we are on a background thread.
*/
method();
return null;
}
#Override
protected void done() {
/* Executing method on Event Dispatch Thread.
* The loading bar should stop because method() is time consuming and everything on the Event Dispatch Thread
* (like the motion of the progress bar) is waiting for it to finish.
*/
//
method();
}
}
}
Hope this helps.
I have got a tricky problem. I need to pop a confirm message box for user to decide close or not when someone click the close sign on the right upper corner of the window. But It doesn't work. Whatever you choose in the pop message box , the dialog will always be closed. But the same logic works fine when I create a JFrame.
Below is my code in my netbeans IED.
I just use a WindowAdpter to catch the close event, plz igore the dummy code generated by neatbean.
Thanks.
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class TestClosingDialog extends javax.swing.JDialog {
public TestClosingDialog(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
this.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
int a = JOptionPane.showConfirmDialog(null,"Are you sure you need to close?", "Tip", JOptionPane.YES_NO_OPTION);
if (a == 0) {
System.out.println("yes " + a);
System.exit(0); //close
} else if (a==1) {
System.out.println("no " + a);
}
}
});
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
#SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 300, Short.MAX_VALUE)
);
pack();
}// </editor-fold>
/**
* #param args the command line arguments
*/
public static void main(String args[]) {
/* Set the Nimbus look and feel */
//<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
*/
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(TestClosingDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(TestClosingDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(TestClosingDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(TestClosingDialog.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
//</editor-fold>
/* Create and display the dialog */
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
TestClosingDialog dialog = new TestClosingDialog(new JFrame(), true);
dialog.setVisible(true);
}
});
}
// Variables declaration - do not modify
// End of variables declaration
}
Change setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); to setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING);
This will require you to manually dispose of the dialog. Depending on your needs, you would simply need to change System.exit(0); to dispose();
I would, personally, advise against extending directly from a top level container like JDialog, but that's just me.
I prefer to use, something like, a JPanel that has a helper method that can display an dialog. This method would create the dialog and add the panel to it, for example
trying to get an image to print into a window. Everything runs without errors, and it also works if I replace the drawImage with another graphics class. However, the window is missing the image, and i'm not sure why. Again, the JFrame stuff and Graphics work fine with drawing other graphics, but only doesn't draw the image here. Thanks.
import javax.swing.JApplet;
import javax.swing.JFrame;
import javax.imageio.*;
import javax.imageio.stream.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
public class GraphicsMovement2 extends JApplet{
BufferedImage image = null;
public static void main(String args[]){
BufferedImage image = null;
try {
File file = new File("C:\\Users/Jonheel/Google Drive/School/10th Grade/AP Computer Science/Junkbin/MegaLogo.png");
ImageInputStream imgInpt = new FileImageInputStream(file);
image = ImageIO.read(file);
}
catch(FileNotFoundException e) {
System.out.println("x");
}
catch(IOException e) {
System.out.println("y");
}
JApplet example = new GraphicsMovement2();
JFrame frame = new JFrame("Movement");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(example);
frame.setSize(new Dimension(1366,768)); //Sets the dimensions of panel to appear when run
frame.setVisible(true);
}
public void paint (Graphics page){
page.drawImage(image, 100, 100, 100, 100, Color.RED, this);
}
}
You've defined image twice...
BufferedImage image = null;
public static void main(String args[]){
BufferedImage image = null;
This essentially means that by the time you get to the paint method, it is null as you haven't initialized the instance variable.
Another problem you will have is the fact that you are trying to load the image from a static reference but the image isn't declared as static. Better to move this logic into the constructor or instance method.
Don't use JApplet as your container when you're adding to a JFrame, you're better of using something like JPanel. It will help when it comes to adding things to the container.
YOU MUST CALL super.paint(g)...in fact, DON'T override the paint method of top level containers like JFrame or JApplet. Use something like JPanel and override the paintComponent method instead. Top level containers aren't double buffered.
The paint methods does a lot of important work and it's just easier to use JComponent#paintComponent ... but don't forget to call super.paintComponent
UPDATED
You need to define image within the context it is going to be used.
Because you declared the image as an instance field of GraphicsMovement2, you will require an instance of GraphicsMovement2 in order to reference it.
However, in you main method, which is static, you also declared a variable named image.
The paint method of GraphicsMovement2 can't see the variable you declared in main, only the instance field (which is null).
In order to fix the problem, you need to move the loading of the image into the context of a instance of GraphicsMovement2, this can be best achived (in your context), but moving the image loading into the constructor of GraphicsMovement2
public GraphicsMovement2() {
try {
File file = new File("C:\\Users/Jonheel/Google Drive/School/10th Grade/AP Computer Science/Junkbin/MegaLogo.png");
ImageInputStream imgInpt = new FileImageInputStream(file);
image = ImageIO.read(file);
}
catch(FileNotFoundException e) {
System.out.println("x");
}
catch(IOException e) {
System.out.println("y");
}
}
The two examples below will produce the same result...
The Easy Way
public class TestPaintImage {
public static void main(String[] args) {
new TestPaintImage();
}
public TestPaintImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ImagePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ImagePane extends JPanel {
public ImagePane() {
setLayout(new BorderLayout());
ImageIcon icon = null;
try {
icon = new ImageIcon(ImageIO.read(new File("/path/to/your/image")));
} catch (Exception e) {
e.printStackTrace();
}
add(new JLabel(icon));
}
}
}
The Hard Way
public class TestPaintImage {
public static void main(String[] args) {
new TestPaintImage();
}
public TestPaintImage() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new ImagePane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class ImagePane extends JPanel {
private BufferedImage background;
public ImagePane() {
try {
background = ImageIO.read(new File("/path/to/your/image"));
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public Dimension getPreferredSize() {
return background == null ? super.getPreferredSize() : new Dimension(background.getWidth(), background.getHeight());
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
int x = (getWidth() - background.getWidth()) / 2;
int y = (getHeight() - background.getHeight()) / 2;
g.drawImage(background, x, y, this);
}
}
}
}
Take the time to read through the tutorials
Creating a GUI With JFC/Swing
Performing Custom Painting
Your class shouldn't extend JApplet when you're not even using applets -- this makes no sense. Instead
Have your drawing class extend JPanel
Draw in the JPanel's paintComponent method
Add this JPanel to the JFrame's contentPane.
Read the Swing painting tutorials. You can't guess at this stuff and expect it to work, and the tutorials will show you how it's done correctly.
Don't mix file deviders,
File file = new File("C:\\Users/Jonheel/Google Drive/School/10th Grade/AP Computer Science/Junkbin/MegaLogo.png");
should be replaced with:
File file = new File("C:/Users/Jonheel/Google Drive/School/10th Grade/AP Computer Science/Junkbin/MegaLogo.png");
How do I create a window which looks like this in Java:
I want that window layout, instead of the standard Windows-borders, and I don't know how this is called.
Edit: look and feel doesn't work for me:
If you want your Look and Feel to draw the window decoration (that's what the "border" is called), then you need to call JFrame.setDefaultLookAndFeelDecorated(true) before creating your JFrame objects and JDialog.setDefaultLookAndFeelDecorated(true) before creating your JDialog objects.
that's called look and feel, you can find a detailed explanation here http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html
You will need to first set the look and feel to use the cross platform look and feel (As someone commented before it's called metal). Then before you create the Frame you need to request that the borders are drawn by the look and feel.
try
{
UIManager.setLookAndFeel(
UIManager.getCrossPlatformLookAndFeelClassName());
}
catch (Exception e) { }
This will set the look and feel to the one you want. As the cross platform look and feel is metal in Sun's JRE.
// Get window decorations drawn by the look and feel.
JFrame.setDefaultLookAndFeelDecorated(true);
// Create the JFrame.
JFrame frame = new JFrame("A window");
And this will make the created JFrame have borders like you describe.
Add this to your main() method:
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException ex) {
java.util.logging.Logger.getLogger(testjframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (InstantiationException ex) {
java.util.logging.Logger.getLogger(testjframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (IllegalAccessException ex) {
java.util.logging.Logger.getLogger(testjframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
} catch (javax.swing.UnsupportedLookAndFeelException ex) {
java.util.logging.Logger.getLogger(testjframe.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
}
To set windows look and feel for swing write following code in main method.
public static void main(String args[]) {
try {
for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
if ("windows".equalsIgnoreCase(info.getName())) {
javax.swing.UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception ex) {
System.out.println(e);
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
MainFrame mainFrame = new MainFrame();
mainFrame.setExtendedState(MAXIMIZED_BOTH);
mainFrame.setVisible(true);
InitDatabaseDialog initDatabaseDialog = new InitDatabaseDialog(mainFrame, true);
initDatabaseDialog.setVisible(true);
}
});
}