In my main class, I call a class that, upon instantiation, should display its JFrame window. However, that is not the case. I've had this class work before, when I ran the project through Eclipse. Now, running it through command line, it does not work :(.
From my main method:
PaintTitleMovie q = new PaintTitleMovie();
The Jframe class:
public class PaintTitleMovie extends JPanel implements MouseListener {
Image image;
Font ConfettiFinal = new Font("Analog", 1, 20); // fail safe
static JFrame frame = new JFrame();
public PaintTitleMovie() {
image = Toolkit.getDefaultToolkit().createImage("src/Title2.gif");
try {
Font Confetti = Font.createFont(Font.TRUETYPE_FONT, new File(
"src/Fonts/Confetti.ttf"));
ConfettiFinal = Confetti.deriveFont(1, 50);
} catch (FontFormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
addMouseListener(this);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
g.drawImage(image, 0, 0, this);
}
// draw exit button
g.setColor(Color.BLUE);
g.fillRect(990, 50, 210, 100);
g.setColor(Color.BLACK);
g.fillRect(1000, 60, 190, 80);
g.setColor(Color.WHITE);
g.setFont(ConfettiFinal);
g.drawString("Continue", 1000, 120);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
frame.add(new PaintTitleMovie());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(1200, 800);
frame.setUndecorated(true);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
SongTitle s = new SongTitle();
}
});
}
#Override
public void mouseReleased(MouseEvent arg0) {
// TODO Auto-generated method stub
int x = arg0.getX();
int y = arg0.getY();
if (x >= 990 && y >= 50 && y <= 150) {
this.setVisible(false);
frame.dispose();
PaintMenu load = new PaintMenu(); // load paint menu
}
}
}
This src/Title2.gif is going to be problem, the src directory will not exist when the program is built.
Toolkit.getDefaultToolkit().createImage(String) also assumes that the resource is file on the file system, but anything that is contained within the application context (or jar file) is consider an embedded resource and can not be treated as a file.
Instead, you could need to use something more like
image = ImageIO.read(getClass().getResource("/Title2.gif"));
This will return a BufferedImage but will also throw an IOException if the image can not be loaded. If the gif is an animated gif you will need to use something more like
image = new ImageIcon(getClass().getResource("/Title2.gif"));
The same will go for your font, but in that case you will likely need to use
Font Confetti = Font.createFont(Font.TRUETYPE_FONT, getClass().getResourceAsStream(
"/Fonts/Confetti.ttf"));
If you're using Eclipse, you may need to move these resources out the the src directory and in a "resources" directory at the same level as the src directory in order for them to be included in the final build.
Related
I work on a Java development software with Swing and I have a problem with my code, I want to display an image with the LoadingFrame class, its main work but when I call the constructor and the start() method in my main class, the frame opens but the image doesn't display (I have no Exception).
Why it doesn't work with my main class?
public class LoadingFrame
{
private JFrame frame;
public LoadingFrame()
{
frame = new JFrame();
frame.setSize(800, 600);
frame.setLocationRelativeTo(null);
frame.setUndecorated(true);
frame.setContentPane(new Panneau());
}
public void start()
{
frame.setVisible(true);
}
public void stop()
{
frame.setVisible(false);
}
public static void main(String[] args)
{
LoadingFrame l = new LoadingFrame();
l.start();
try
{
Thread.sleep(3000);
}
catch(Exception e)
{
e.printStackTrace();
}
l.stop();
}
}
public class Panneau extends JPanel
{
public void paintComponent(Graphics g)
{
System.out.println("hello");
try
{
Image img = ImageIO.read(new File("Images/loading.png"));
//g.drawImage(img, 0, 0, this);
//Pour une image de fond
g.drawImage(img, 0, 0, this.getWidth(), this.getHeight(), this);
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
The App class is my main class :
public class App {
//Attributes used to display the application
private JFrame frame;
//Attribute which display a waiting frame
private static LoadingFrame loadingFrame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
loadingFrame = new LoadingFrame();
loadingFrame.start();
App window = new App();
loadingFrame.stop();
window.frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public App()
{
initialize();
synchronizeScriptReferenceList();
synchronizeTests();
}
[...]
}
I was able to get this to work from App.java. For some reason, using EventQueue isn't cutting it. I tried to use SwingUtilities as well, but that doesn't work either. Finally I tried just get rid of the Thready-stuff in App.main at just straight up running it in the main thread. For some reason, this works when the other approaches do not! Here is my code:
// In the App class:
public static void main(String[] args) {
try {
loadingFrame = new LoadingFrame();
loadingFrame.start();
App window = new App();
loadingFrame.stop();
window.frame.setVisible(true);
}
catch (Exception e)
{
e.printStackTrace();
}
}
When I used this code, I got it to work! (for some reason unknown to me), And here's a bonus rewrite of the Panneau class:
class Panneau extends JPanel
{
Image img;
public Panneau() {
try
{
img = ImageIO.read(new File("Images/loading.png"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
}
}
There are two main difference with this class; problems which I addressed. Here they are:
I call super.paintComponent as the very first method in our own paintComponent
I only load the loading image once, in the constructor, and not every single time I want to draw, which moves everything along much smoother. (you don't want the loading screen to be CPU heavy, do you?)
Hopefully, with these improvements, I hope you can make your program work! It worked with me, so I wish the best of luck to you.
P.S. Don't call frame.pack(), that was a mistake on my part. For some reason, I think it doesn't work well with undecorated windows.
I am facing an issue that I am not able to draw an png image into my swing GUI into JPanel (which I am adding into JScrollPane after).
Here is my code I am trying to use for this.
if(processCreated == true){
System.out.println("updating tree of organisms");
processCreated = false;
updateTree();
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
Logger.getLogger(Svet.class.getName()).log(Level.SEVERE, null, ex);
}
tree = new File(path+"/out.png"); //File
try {
treeImage = ImageIO.read(tree); //BufferedImage
tp = new TreePane(treeImage.getScaledInstance( 500, 500 ,treeImage.SCALE_SMOOTH)); // my class, implementation below
treeOutput.add(tp); //adding "JPanel" with picture into GUI
treeOutput.repaint();
} catch (IOException ex) {
Logger.getLogger(Svet.class.getName()).log(Level.SEVERE, null, ex);
}
}
After this the JScrollPane remains empty. Is there anything wrong with my code? You can find what is what in comments.
Here is my TreePane class
public class TreePane extends JPanel{
Image img;
public TreePane( Image img ){
this.img = img;
}
public void paintComponent(Graphics g){
super.paintComponent(g);
int imgX = 0;
int imgY = 0;
g.drawImage(img, imgX, imgY, this);
}
}
Very likely your TreePane is layed out to size 0,0 and therefore you'll never see anything. Try adding a breakpoint and inspecting in paintComponent - it might not even ever get called.
To fix, you should explicitly set the size of your TreePane before adding it to the JScrollPane.
tp = new TreePane(treeImage.getScaledInstance( 500, 500 ,treeImage.SCALE_SMOOTH)); // my class, implementation below
tp.setSize(myWidth, myHeight);
treeOutput.add(tp); //adding "JPanel" with picture into GUI
treeOutput.repaint();
Code works, my bad. But I'm still open to suggestions on how to improve or make the code more elegant.
I have created this layout and I want to be able to draw a circle whenever the user clicks on the white area.
Couldn't post an image, so here is the link
The white area is basically a rectangle. But something with my code isn't working, it just doesn't respond to mouse clicks. When I tried to see if it responds to mouseDragged it worked perfectly but this isn't what I need.
Here is my code, some "tests" are put as /comments/ but neither of them work as intended.
I would be very grateful for help. Here is my code:
import java.awt.*;
import java.awt.Graphics;
import javax.swing.*;
public class CitiesMapPanel extends JPanel implements MouseListener {
private JButton cmdAddWay, cmdFindPath, cmdClearMap, cmdClearPath;
private JLabel lblFrom, lblTo;
private JTextField txtFrom, txtTo;
public CitiesMapPanel() {
cmdAddWay = new JButton("Add Way");
cmdFindPath = new JButton("Find Path");
cmdClearMap = new JButton("Clear Map");
cmdClearPath = new JButton("Clear Path");
lblFrom = new JLabel("From");
lblTo = new JLabel("To");
txtFrom = new JTextField(6);
txtTo = new JTextField(6);
this.addMouseListener(this);
setLayout(new BorderLayout());
add(buildGui(), BorderLayout.SOUTH);
}
private JPanel buildGui() {
JPanel buttonsBar = new JPanel();
//The "south" of the BorderLayout consist of a (2,4) GridLayout.
buttonsBar.setLayout(new GridLayout(2,4));
buttonsBar.add(lblFrom);
buttonsBar. add(txtFrom);
buttonsBar.add(lblTo);
buttonsBar.add(txtTo);
buttonsBar.add(cmdAddWay);
buttonsBar.add(cmdFindPath);
buttonsBar.add(cmdClearMap);
buttonsBar.add(cmdClearPath);
return buttonsBar;
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(0, 0, this.getSize().height, this.getSize().width);
}
public static void main(String[] args) {
JFrame frame = new JFrame("layout");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(530, 550);
CitiesMapPanel gui = new CitiesMapPanel();
frame.add(gui);
frame.setVisible(true);
}
/*abstract private class MyMouseListner implements MouseListener{
public void mouseClicked(MouseEvent e){
int x = e.getX();
int y = e.getY();
Graphics g = getGraphics();
g.setColor(Color.black);
g.fillOval(x,y,15,15);
}
}*/
#Override
public void mouseClicked(MouseEvent e) {
int x = e.getX();
int y = e.getY();
Graphics g = getGraphics();
g.setColor(Color.black);
g.fillOval(x,y,15,15);
System.out.println("test");
}
#Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
#Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
}
The click listener is not the problem. Your approach to painting is simply wrong. You can't do a getGraphic, paint on it, and expect the result to be presented. In Swing (AWT) things work fundamentally different. You need to either create an off screen image that you paint to and that you then present on screen in your paintComponent method, or you need to track the objects you want to paint in a data structure and paint those in your paintComponent method. You can trigger a repaint in your click listener by calling repaint so the UI subsystems knows about the changed state that requires a repaint of your component.
Read more about the basics in the Swing painting tutorial.
Hi there I'm new to GUIs in Java and was trying to make a splash screen or an image appear for 3 seconds. Then after that it it will go onto my main program. Does anyone have an ideas how to do this or can link me to any tutorials?
So far I have done this but not sure where to go from here.
public static void main(String[] args)
{
splashInit(); // initialize splash overlay drawing parameters
appInit(); // simulate what an application would do
}
Simplest one , is to create JFrame and add your screen on it then use Thread.Sleep(long millies)
Try this code:
JWindow window = new JWindow();
window.getContentPane().add(
new JLabel("", new ImageIcon(new URL("http://docs.oracle.com/javase/tutorial/uiswing/examples/misc/SplashDemoProject/src/misc/images/splash.gif")), SwingConstants.CENTER));
window.setBounds(500, 150, 300, 200);
window.setVisible(true);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
window.setVisible(false);
JFrame frame = new JFrame();
frame.add(new JLabel("Welcome"));
frame.setVisible(true);
frame.setSize(300,100);
window.dispose();
Or you can Create a Splash Screen by using SplashScreen class
See also How to Create a Splash Screen for the AWT based splash functionality.
To print messages on the splash screen, you need to add a picture to your application and add it to the manifest.mf:
SplashScreen-Image: path/picture.jpg
Then use code like this:
private static Graphics2D splashGraphics = null;
private static SplashScreen splash;
private static int dpi;
public static void main(String[] args) {
initSplashMessages();
splashMessage("Start program...");
...
splashMessage("Load data...");
...
}
private static void initSplashMessages() {
splash = SplashScreen.getSplashScreen();
if (splash == null) return;
splashGraphics = splash.createGraphics();
if (splashGraphics == null) return;
dpi = Toolkit.getDefaultToolkit().getScreenResolution();
}
public static void splashMessage(String message) {
if (splashGraphics == null) return;
Dimension dim = splash.getSize();
splashGraphics.setColor(Color.LIGHT_GRAY);
splashGraphics.fillRect(0, dim.height - dpiX(20), dim.width, dpiX(20));
splashGraphics.setPaintMode();
splashGraphics.setColor(Color.BLACK);
splashGraphics.setFont(new Font("Arial",Font.PLAIN, dpiX(12)));
splashGraphics.drawString(message, dpiX(3), dim.height - dpiX(5));
splash.update();
}
private static int dpiX(int x) {
return (int) Math.round(1.0 * x * dpi / 96);
}
In IntelliJ add the picture.jpg to your project (use File):
For debugging use "Modify options"/"Add VM options" and write
-splash:path/picture.jpg
This works fine for me.The functions such as getScreenSize() ,getWidth() and getHeight() can be replaced by own values.
public class splash extends JWindow
{
public splash()
{
JWindow j=new JWindow();
Dimension d=Toolkit.getDefaultToolkit().getScreenSize();
Icon img= new ImageIcon(this.getClass().getResource("2.jpg"));
JLabel label = new JLabel(img);
label.setSize(200,300);
j.getContentPane().add(label);
j.setBounds(((int)d.getWidth()-722)/2,((int)d.getHeight()-401)/2,722,401);
j.setVisible(true);
try
{
Thread.sleep(6000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
j.setVisible(false);
}
public static void main(String[] args)
{
splash s=new splash();
}
}
I use this code. Maybe you need to change some parts:
import javax.swing.*;
import java.awt.*;
public class SplashScreen {
private final JWindow window;
private long startTime;
private int minimumMilliseconds;
public SplashScreen() {
window = new JWindow();
var image = new ImageIcon("C:\\example.jpg");
window.getContentPane().add(new JLabel("", image, SwingConstants.CENTER));
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
window.setBounds((int) ((screenSize.getWidth() - image.getIconWidth()) / 2),
(int) ((screenSize.getHeight() - image.getIconHeight()) / 2),
image.getIconWidth(), image.getIconHeight());
}
public void show(int minimumMilliseconds) {
this.minimumMilliseconds = minimumMilliseconds;
window.setVisible(true);
startTime = System.currentTimeMillis();
}
public void hide() {
long elapsedTime = System.currentTimeMillis() - startTime;
try {
Thread.sleep(Math.max(minimumMilliseconds - elapsedTime, 0));
} catch (InterruptedException e) {
e.printStackTrace();
}
window.setVisible(false);
}
}
And here is how to use it:
var splash = new SplashScreen();
splash.show(2000);
// Initializing...
splash.hide();
This will show the splash at least 2 seconds.
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");