BufferedImage only Appears when Window is Minimized and Re-Maximized - java

I'm currently writing an application using Java Swing. So far, the application is simple, it creates a window (JFrame) that fills the screen. This JFrame has a main JPanel, and in that JPanel is a JLabel for the title and a JLabel that I'm loading a BufferedImage into. When I run the program, the JLabel containing the title shows up, but the JLabel containing the image I'm loading in doesn't appear. However, when I hit the "minimize" button on the window, and then maximize the window again, the image appears as it should. Why isn't the image showing up when the program is opened? My code is shown below:
public class MainWindow extends JFrame {
private static final int DEFAULT_WIDTH = 1400;
private static final int DEFAULT_HEIGHT = 800;
private JPanel mainPanel;
public MainWindow() {
setup();
}
private void setup() {
this.setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);
this.mainPanel = new JPanel(new BorderLayout());
mainPanel.setBackground(Color.BLUE);
this.add(mainPanel);
setupObjectInsertPanel();
}
private void setupObjectInsertPanel() {
JLabel label = new JLabel("TileSets");
mainPanel.add(label, BorderLayout.NORTH);
try{
BufferedImage tilesetImage = ImageIO.read(new File(...)); // path ommitted
JLabel tilesetIcon = new JLabel(new ImageIcon(tilesetImage));
mainPanel.add(tilesetIcon, BorderLayout.SOUTH);
System.out.println("Loaded tileset into panel");
} catch (IOException e) {
System.out.println("Could not open tileset");
e.printStackTrace();
}
}
}
The try statement always succeeds, and the success message is printed when the program starts up, but the image isn't showing up until the window is minimized/re-maximized. Why is this behavior happening?

Related

Java Swing JLabel.setIcon() not working the way I expect

I have a probably easy to solve problem. I used Intellij Idea to build a GUI form. Now I am trying to change the imageIcon of the imageLabel JLabel.
I don't really understand why but when I use the JLabel.setIcon() it neither throws an exception nor displays the image. I have no idea what is wrong with it. It seems like a very simple command.
( I added ico.getImage().flush(); line because when I was searching around people said you have to flush the image before displaying it. I don't actually know what that line does.)
Thanks for any help.
public class App
{
private JPanel mainPanel;
private JPanel imagePanel;
private JPanel optionsPanel;
private JPanel palletesPanel;
private JPanel buttonsPanel;
private JPanel originalPalletePanel;
private JPanel newPalletePanel;
private JLabel originalPalleteLabel;
private JLabel newPalleteLabel;
private JPanel leftButtonsPanel;
private JPanel rightButtonsPanel;
private JButton previewButton;
private JButton revertButton;
private JButton convertImageButton;
private JButton matchPalleteButton;
private JLabel originalPalleteImageLabel;
private JLabel newPalleteImageLabel;
private JLabel imageLabel;
public static void main(String[] args)
{
App app = new App();
JFrame frame = new JFrame("Pixel Pigeon");
frame.setContentPane(new App().mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
pigeon pigey = new pigeon();
try
{
app.loadImage(frame, app);
}
catch(java.io.IOException e)
{
e.printStackTrace();
}
}
private void loadImage(JFrame frame, App app) throws IOException
{
JFileChooser chooser = new JFileChooser();
if(chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION)
{
BufferedImage img = ImageIO.read(chooser.getSelectedFile());
ImageIcon ico = new ImageIcon(img);
ico.getImage().flush();
app.imageLabel.setIcon(ico);
}
}
}
There were a lot of problems with that short section of code. After removing the many redundant components, the reference to a class not in evidence, fixing the two instances of NullPointerException, removing the call to flush the image, and fixing the problem with the new creation of an App() that already existed, it 'works'. But it is still so bad I'd recommend tossing the lot out and starting again with reference to the JavaDocs for investigating things random people recommend, and the Java Tutorial for the basics of GUI development.
So here is the 'fixed' code: It will load an image, but the GUI then needs to be stretched to make the image visible.
import java.awt.image.BufferedImage;
import java.io.*;
import javax.swing.*;
import javax.imageio.ImageIO;
public class App {
private JPanel mainPanel = new JPanel();
private JLabel imageLabel = new JLabel();
public static void main(String[] args) {
App app = new App();
JFrame frame = new JFrame("Pixel Pigeon");
app.mainPanel.add(app.imageLabel);
frame.setContentPane(app.mainPanel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
try {
app.loadImage(frame, app);
}
catch(java.io.IOException e) {
e.printStackTrace();
}
}
private void loadImage(JFrame frame, App app) throws IOException {
JFileChooser chooser = new JFileChooser();
if(chooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
BufferedImage img = ImageIO.read(chooser.getSelectedFile());
ImageIcon ico = new ImageIcon(img);
app.imageLabel.setIcon(ico);
}
}
}

Panel won't open?

I am making a pacman game. The plan is to have a GUI that will show the welcome page and a JButton that reads "Play." After the user presses the "Play" button, it will open a new panel that will have an image that will consist of the instructions. On the instructions panel, there will be a JButton that reads "Continue." This will take the user to a GUI with four JButtons reading "Easy," "Medium," "Hard," and "QUIT." The actionPerformed methods for these buttons have already been coded and it works properly (a new JFrame will open with the corresponding Panel to each level, QUIT will quit the program).
The way I created this is that I made a class called GUIPanel and all the panels will open when the GUIPanel object is instantiated.
After I completed the GUI with the levels, that's when I decided to add the Welcome panel and and Instructions panel. So far, I have written code for the Welcome panel. I added it above the code for the level-buttons.
My problem is that whenever I run it, a frame is created but there is no panel. PLEASE HELP ME!! THIS PROJECT IS DUE TOMORROW.
//*****************************
// GUI : Panel
//
// Updated : May 4th, 2017
//
//*****************************
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.io.*;
public class GUIPanel extends JPanel
{
private Graphics g;
private BufferedImage buffer;
public GUIPanel()
{
try{
//welcome panel
JPanel welcome = new JPanel();
ImageIcon title = new ImageIcon("welcome.png");
buffer = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB);
g = buffer.getGraphics();
g.drawImage(title.getImage(), 400, 400, 200, 200, null);
//add button and listener and add onto welcome (JPanel)
JButton play = new JButton("Play");
play.addActionListener(new PlayListener());
welcome.add(play);
}
catch(Exception e){
}
}
private class PlayListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
try{
JFrame playFrame = new JFrame();
//creating the panel
JPanel panel = new JPanel();
add(panel);
/*creating the Easy button which will allow the
user to play the EASY LEVEL of Karelman */
JButton easyButton = new JButton("Easy");
easyButton.setBackground(Color.BLUE);
easyButton.setForeground(Color.WHITE);
easyButton.addActionListener(new EasyListener());
panel.add(easyButton);
/*creating the Medium button which will allow the
user to play the MEDIUM LEVEL of Karelman */
JButton mediumButton = new JButton("Medium");
mediumButton.setBackground(Color.BLUE);
mediumButton.setForeground(Color.WHITE);
mediumButton.addActionListener(new MediumListener());
panel.add(mediumButton);
/*creating the random button which will allow the
user to play the HARD LEVEL of Karelman*/
JButton hardButton = new JButton("Hard");
hardButton.setBackground(Color.BLUE);
hardButton.setForeground(Color.WHITE);
hardButton.addActionListener(new HardListener());
hardButton.setBounds(40, 100, 100, 60);
panel.add(hardButton);
/*creating the quit button for exiting the program*/
JButton quitButton = new JButton("QUIT");
quitButton.setBackground(Color.BLUE);
quitButton.setForeground(Color.WHITE);
quitButton.addActionListener(new QuitListener());
quitButton.setBounds(150, 300, 25, 25);
panel.add(quitButton);
}
catch(Exception i){
}
}
}
/*
EasyListener is attached to the Easy Button
It will open the Easy Level by creating a
new frame which will use Easy Ghosts.
*/
private class EasyListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
try{
JFrame frame = new JFrame("PLAY KARELMAN -- EASY");
frame.setSize(708, 738);
frame.setLocation(350, 0);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//create panel for Easy Level within frame
EasyPanel easy = new EasyPanel();
frame.setContentPane(easy);
}
catch(IOException i){
}
}
}
/*
MediumListener is attached to the Medium Button
It will open the Medium Level by creating a
new frame which will use Medium Ghosts.
*/
private class MediumListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
try{
JFrame frame = new JFrame("PLAY KARELMAN -- MEDIUM");
frame.setSize(708, 738);
frame.setLocation(350, 0);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//create panel for Medium Level within frame
MediumPanel medium = new MediumPanel();
frame.setContentPane(medium);
}
catch(IOException i){
}
}
}
/*
HardListener is attached to the Hard Button
It will open the Hard Level by creating a
new frame which will use Hard Ghosts.
*/
private class HardListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
try{
JFrame frame = new JFrame("PLAY KARELMAN -- HARD");
frame.setSize(708, 738);
frame.setLocation(350, 0);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
//create panel for Hard Level within frame
HardPanel hard = new HardPanel();
frame.setContentPane(hard);
}
catch(IOException i){
}
}
}
/*
QuitListener is attached to the Quit Button
It will make a system call to exit the program.
*/
private class QuitListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
System.exit(0);
}
}
}

Java program Class Menu

I have to use the function of this class in another class in action_performed. This code is giving me error.
public class Menu {
public void Menu()
{
try {
Image img = ImageIO.read(getClass().getResource("Image1.jpg"));\\to get image
Image img1 = ImageIO.read(getClass().getResource("Image2.jpg"));
Image img2 = ImageIO.read(getClass().getResource("Image3.png"));
Image img3 = ImageIO.read(getClass().getResource("Image4.jpg"));
Image img4= ImageIO.read(getClass().getResource("Image5.jpg"));
Image img5= ImageIO.read(getClass().getResource("Image6.jpg"));
JFrame f1=new JFrame("Menu");
f1.setSize(400,200);
f1.setVisible(true);
JPanel P1=new JPanel();
P1.setVisible(true);
JButton b1=new JButton("Creamy Chocolate Cup");
b1.setIcon(new ImageIcon(img));
b1.add(P1);
b1.setVisible(true);
P1.add(f1);
} catch (IOException ex) {
}
}
}
Cant add more details and this is all I can tell Just tell me how to solve this problem as quick as possible.
Remove the line:
P1.add(f1);
This will give you a java.lang.IllegalArgumentException because you are trying to add a window to a container. It should work if you remove that line.
However, your code is totally incorrect. You are adding a JFrame to a JPanel and adding the JPanel to the JButton, it should be the opposite way around.
For example, this will work for you:
public void Menu()
{
Image img = ImageIO.read(getClass().getResource("Image1.jpg"));
JFrame f1=new JFrame("Menu");
f1.setSize(400,200);
JPanel P1=new JPanel();
JButton b1=new JButton("Creamy Chocolate Cup");
b1.setIcon(new ImageIcon(img));
P1.add(b1);
f1.add(P1);
f1.setVisible(true);
}

Swing Intellij GUIDesigner image disappears if placed in JScrollPane

I'm using IntelliJ GUIDesigner.
I have JScrollPanel which contains JPanel.
The idea is that I want to add image to JPanel and to have it load at full size so I can use scrollers to move around and see whole image.
And My problem is that it paints itself alright if I won't change the size of JPanel. But the moment I'm chaning JPanel size it just repaints itself to orginal state (I suppose, IntelliJ hides a lot of code from me).
The code is:
private JPanel panel1;
private JButton button1;
private JPanel drawingPanel;
public MainPanel(){
button1.addActionListener(e -> {
JFileChooser openFile = new JFileChooser();
File chosenFile;
if(openFile.showSaveDialog(panel1) == JFileChooser.APPROVE_OPTION){
chosenFile = openFile.getSelectedFile();
drawImage(chosenFile);
}
});
}
private void drawImage(File file){
try {
BufferedImage image = ImageIO.read(file);
//Works OK if line belowed is removed, but doesn't adjust size so I can't scroll.
drawingPanel.setSize(image.getWidth(), image.getHeight());
Graphics g = drawingPanel.getGraphics();
g.drawImage(image, 0, 0, null);
drawingPanel.paintComponents(g);
}
catch (IOException e) {
e.printStackTrace();
}
}
As I wrote in comment, if the line below the comment is removed then I can load the image and it shows OK but it's too big and I can't see whole image.
If I add the line then it just clears everything and I can't see nothing.
This is important - I need to get the image to show in full size.
How do I do it?
I have JScrollPanel which contains JPanel.
Don't do custom painting.
Just create a JLabel and add the label to the viewport of the scroll pane. Then when you want to change the image you use the setIcon(...) method of the JLabel and the label will automatically repaint itself and scrollbars will appear if necessary.
Maybe you can share your IntelliJ GUI forms? Otherwise it's difficult to reproduce the scrolling problem that you're facing. Without the custom painting and using a label as camickr suggested, you can get scrolling working like this:
public class MainPanel {
private static JFrame frame;
private JPanel panel1;
private JButton button1;
private JPanel drawingPanel;
private JLabel drawingLabel;
public static void main(String[] args) {
MainPanel.test();
}
private static void test() {
frame = new JFrame("");
frame.setBounds(100, 100, 640, 480);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
new MainPanel();
frame.setVisible(true);
}
public MainPanel() {
initializeGui();
button1.addActionListener(e -> {
JFileChooser openFile = new JFileChooser("[...]");
File chosenFile;
if (openFile.showSaveDialog(panel1) == JFileChooser.APPROVE_OPTION) {
chosenFile = openFile.getSelectedFile();
System.out.println("chosenFile: " + chosenFile);
drawImage(chosenFile);
}
});
}
private void initializeGui() {
panel1 = new JPanel(new BorderLayout());
frame.getContentPane().add(panel1);
button1 = new JButton("Open image");
panel1.add(button1, BorderLayout.NORTH);
drawingPanel = new JPanel(new BorderLayout());
panel1.add(drawingPanel, BorderLayout.CENTER);
drawingLabel = new JLabel();
drawingPanel.add(new JScrollPane(drawingLabel), BorderLayout.CENTER);
}
private void drawImage(File file){
try {
BufferedImage image = ImageIO.read(file);
//Works OK if line below is removed, but doesn't adjust size so I can't scroll.
// drawingPanel.setSize(image.getWidth(), image.getHeight());
// Graphics g = drawingPanel.getGraphics();
// g.drawImage(image, 0, 0, null);
// drawingPanel.paintComponents(g);
drawingLabel.setIcon(new ImageIcon(image));
drawingPanel.validate();
}
catch (IOException e) {
e.printStackTrace();
}
}
}
Not sure how easy it is to do something similar with the IntelliJ GUI designer; I do prefer IntelliJ (over Eclipse and NetBeans) but I also prefer to create my Java GUIs in code... ;-)

Translucent loading overlay for JFrame

I have a JFrame containing various components and I would like to add a translucent grey overlay over the top while the application is initializing various things. Ideally it would prevent interaction with the underlying components and would be able to display some "Loading..." text or a spinning wheel or something similar.
Is there a simple way to do this using Java and Swing?
Take a look at JRootPane and JLayeredPane http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html#layeredpane
What you're asking about specifically sounds like a Glass Pane.
http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html#glasspane
The Glass Pane prevents interaction with underlying components and can be used to display something on top of your JFrame.
As #David said, you can use the glass pane for displaying some loading text or image above the rest of the application.
As for the grey overlay: why don't you use the built in ability to disable components as long as your application is loading? Disabled components will get grayed out automatically and cannot be interacted with by the user.
Something like this:
public class LoadingFrame extends JFrame{
JButton button;
public LoadingFrame() {
button = new JButton("ENTER");
button.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Application entered");
}
});
setLayout(new BorderLayout());
add(button, BorderLayout.CENTER);
}
public void startLoading(){
final Component glassPane = getGlassPane();
final JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
final JLabel label = new JLabel();
panel.add(label, BorderLayout.SOUTH);
setGlassPane(panel);
panel.setVisible(true);
panel.setOpaque(false);
button.setEnabled(false);
Thread thread = new Thread(){
#Override
public void run() {
for (int i = 5; i > 0; i--) {
label.setText("Loading ... " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// loading finished
setGlassPane(glassPane);
button.setEnabled(true);
}
};
thread.start();
}
public static void main(String[] args) {
LoadingFrame frame = new LoadingFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.startLoading();
frame.setVisible(true);
}
}

Categories

Resources