setImageIcon doesn't set JFrame icon on mac swing window - java

I've already tried loads of code from Stack. For some reason it's just not setting the ImageIcon for my JFrame, the comments are other attempts that have not worked;I avoided calling super so that I could reference the JFrame -- GUIPhotoAlbum extends JFrame; code:
public GUIPhotoAlbum ()
{
super("PhotoAlbum");
ImageIcon img = new ImageIcon("Photos/albumIcon.png");
this.setIconImage(img.getImage());
/*
try{
setIconImage(ImageIO.read(new File("Photos/albumIcon.png")));
}catch(Exception e){
System.out.print("Didn't work.");
}
*/
setSize(875, 625);
this.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
this.setLayout(new BorderLayout(5, 5));
initComponents();
initMenuBar();
initTopPanel();
add(topPanel, BorderLayout.CENTER);
initBottomPanel();
add(bottomPanel, BorderLayout.SOUTH);
addListeners();
setLocationRelativeTo(null);
setVisible(true);
}
EDIT
I'm running the program like this, where I try to set the ImageIcon of JFrame in the GUIPhotoAlbum() constructor; here's the driver:
public class AlbumDriver
{
public static void main (String [ ] args)
{
SwingUtilities.invokeLater
(
new Runnable()
{
#Override
public void run()
{
GUIPhotoAlbum pa = new GUIPhotoAlbum();
}
}
);
}
}
What am I doing wrong here?
PS I've tried BufferedImage, ImageIcon, using File.. and I'm using a Mac

Mac does not support frame icons, as seen in this answer.

Use this to change Dock Image in mac:
File imageFile = new File("Your image Path");
Image image = ImageIO.read(imageFile);
Application.getApplication().setDockIconImage(image);
For windows use this:
YourFrameObject.setIconImage(image);

The problem is, you class appears to be extending from JFrame but you're creating a new instance of a JFrame and setting it's icon instead...
JFrame newFrame = new JFrame("PhotoAlbum");
ImageIcon img = new ImageIcon("Photos/albumIcon.png");
newFrame.setIconImage(img.getImage());
Don't create the second instance of the JFrame, there's no need for newFrame in this instance...
For example...
public GUIPhotoAlbum ()
{
super("PhotoAlbum");
ImageIcon img = new ImageIcon("Photos/albumIcon.png");
setIconImage(img.getImage());
/*
//when uncommented, exception is never thrown
try{
setIconImage(ImageIO.read(new File("Photos/albumIcon.png")));
}catch(Exception e){
System.out.print("Didn't work.");
}
*/
// Hint use pack instead, but only after
// You've finished adding the components to the frame
setSize(875, 625);
setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout(5, 5));
initComponents();
initMenuBar();
initTopPanel();
add(topPanel, BorderLayout.CENTER);
initBottomPanel();
add(bottomPanel, BorderLayout.SOUTH);
addListeners();
setLocationRelativeTo(null);
setVisible(true);
}

Related

How to overlap a JPanel(background) and a JTextField

I am creating a log in application for someones graduation, I need several text fields and a background, I have added the background and now need to add the text fields, the problem is that they won't seem to go on top of each other.
I have tried them each separately and without one another they both work perfectly but i can't get them to stack, I have seen several answers on this site to deal with a similar problem but for this application I need to put several text fields on the background as apposed to just one, here is what I have thus far...
//creates the frame with a title as a parameter
JFrame frame = new JFrame("Sign In Sheet");
//sets the size
frame.setSize(1000, 556);
//makes it so the application stops running when you close it
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//puts it in the center of the screen
frame.setLocationRelativeTo(null);
//makes it so you can't resize it
frame.setResizable(false);
//setting the background by looking for the image
try{
frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("C:/Users/Gabriel R. Warner/Desktop/clouds.png")))));
}catch(IOException e){
//and prints an error message if it's not found
System.out.println("well it didn't work");
}
//adding text fields with names apropriate to function
JTextField name1 = new JTextField();
name1.setPreferredSize(new Dimension(200, 15));
name1.setBackground(Color.WHITE);
frame.add(name1);
//makes frame visible
frame.setVisible(true);
Simply stated the text field won't show up with the background and all the results only offer answers for a single text field
The problem is in this line: frame.setContentPane(new JLabel(new ImageIcon(ImageIO.read(new File("C:/Users/Gabriel R. Warner/Desktop/clouds.png")))));
In this line you set a JLabel as the content pane of your JFrame. Then, you frame.add(name1); So you are adding a JTextField to a JLabel...Well this does not seem right, right?
The answer would be to create a new JPanel, add the background image to this panel, set the panel as the content pane of the frame and finally add the textfield to the panel/contentpane.
An example:
#SuppressWarnings("serial")
public class FrameWithBackgroundImage extends JFrame {
public FrameWithBackgroundImage() {
super("Sign In Sheet");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
try {
Image bgImage = loadBackgroundImage();
JPanel backgroundImagePanel = new JPanel() {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(bgImage, 0, 0, null);
}
};
setContentPane(backgroundImagePanel);
} catch (IOException e) {
e.printStackTrace();
}
JTextField textField = new JTextField(10);
add(textField);
}
private Image loadBackgroundImage() throws IOException {
File desktop = new File(System.getProperty("user.home"), "Desktop");
File image = new File(desktop, "img.jpg");
return ImageIO.read(image);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new FrameWithBackgroundImage().setVisible(true);
});
}
}
Preview:
Worth to read question: Simplest way to set image as JPanel background

Moving a JLabel for a game

I am coding a Backgammon game that plays by itself. While the backend code is mostly done, me and my colleague have pretty much no experience in GUI coding. We used the Designer given by a plugin for Eclipse and most of the code was generated.
So here's the thing. Right now there is a JFrame which has a JPanel in which are 2 JLabels, one for the background and one for 1 playing piece (when I figure this out, the rest of them will be added). These are all in an initialize() method which is run through EventQueue.invokeLater(new Runnable()). After the board and the piece are drawn, the startGame() method is called, which finally comes to a method called movePiece(), with the sole purpose of moving that JLabel piece I talked about before.
I have tried mostly everything I can think of, I have scoured the forums and only found people talking about layouts (which I may or may not be using, as I said, generated code) and the darn JLabel won't move when I call setLocation() inside the movePiece() method. It always throws a NullPointerException at that line which is bizarre because the image is already drawn. I will include part of the code below.
I know this will probably look like some of the worse codes ever, but please bear with my lack of skill and help me make this better. Any insights?
public class Main{
public JLabel image1;
private JFrame frame;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main window = new Main();
window.frame.setVisible(true);
new Main(1);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public Main() {
initialize();
}
public Main(int i){
startGame();
}
public void startGame() {
//game code
movePiece(Move.getPos(), Move.getDest());
//rest of code
}
public void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 1023, 617);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setPreferredSize(new Dimension(800, 700));
JPanel panel_1 = new JPanel();
panel_1.setPreferredSize(new Dimension(200, 700));
frame.getContentPane().add(panel_1, BorderLayout.EAST);
JButton btnNewButton = new JButton("Start Game");
/* ACTION LISTENER FOR THE BUTTON */
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
});
btnNewButton.setFocusable(false);
btnNewButton.setForeground(SystemColor.windowBorder);
btnNewButton.setBackground(SystemColor.menu);
btnNewButton.setVerifyInputWhenFocusTarget(false);
btnNewButton.setRequestFocusEnabled(false);
btnNewButton.setRolloverEnabled(false);
btnNewButton.setFont(new Font("Verdana", Font.PLAIN, 11));
btnNewButton.setDebugGraphicsOptions(DebugGraphics.NONE_OPTION);
/* ADDING THE BTN TO PANEL 1 TO THE RIGHT */
panel_1.add(btnNewButton);
JPanel parentPanel = new JPanel();
parentPanel.setFocusable(false);
parentPanel.setEnabled(false);
parentPanel.setDoubleBuffered(false);
parentPanel.setDebugGraphicsOptions(DebugGraphics.NONE_OPTION);
parentPanel.setIgnoreRepaint(true);
parentPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
parentPanel.setBorder(null);
parentPanel.setPreferredSize(new Dimension(800, 700));
parentPanel.setBackground(SystemColor.menu);
frame.getContentPane().add(parentPanel, BorderLayout.WEST);
/* BACKGAMMON BOARD LABEL-->PANEL */
ImageIcon imageIcon = new ImageIcon(
new ImageIcon("images/bg.png").getImage()
.getScaledInstance(800, 551, Image.SCALE_SMOOTH));
parentPanel.setLayout(null);
ImageIcon imageIcon1 = new ImageIcon(
new ImageIcon("images/pl.png").getImage()
.getScaledInstance(50, 50, Image.SCALE_SMOOTH));
image1 = new JLabel("");
image1.setBounds(37, 36, 50, 50);
parentPanel.add(image1);
image1.setIcon(imageIcon1);
JLabel bg = new JLabel("");
bg.setBounds(10, 11, 800, 551);
bg.setIcon(imageIcon);
parentPanel.add(bg);
}
void movePiece(int pos, int dest) {
//null exception happens here, ignore the arguments
image1.setLocation(37 + 50,36);
}
You create an instance of Main and make it visible...
Main window = new Main();
window.frame.setVisible(true);
You then create a new instance of Main, which, through it's constructor, calls your moviePiece method...
new Main(1);
But the new instance of Main has nothing to do with the previous instance or any of the components which they created.
Instead, trying doing...
window.movePiece(Move.getPos(), Move.getDest());
instead of new Main(1);

JFrame setContentPane hides other components

So I'm going into GUI's in Java, and am trying to create a simple main menu for a timer. All is well until I've attempted to add a background for the GUI. Adding the background works, however all other components are now gone, (the button). How could I fix this?
EDIT: Here is my new code.
public class MainMenu {
// JFrame = the actual menu / frame.
private JFrame frame;
// JLabel = provides text instructions or information on a GUI —
// display a single line of read-only text, an image or both text and an image.
private JLabel background;
// JButton = button.
private JButton alarmClockButton;
// Constructor to create menu
public MainMenu() {
frame = new JFrame("Alarm Clock");
alarmClockButton = new JButton("Timer");
// Add an event to clicking the button.
alarmClockButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO: CHANGE TO SOMETHING NICER
JOptionPane.showMessageDialog(null, "This feature hasn't been implemented yet.", "We're sorry!",
JOptionPane.ERROR_MESSAGE);
}
});
// Creating the background
try {
background = new JLabel(new ImageIcon(ImageIO.read(getClass()
.getResourceAsStream("/me/devy/alarm/clock/resources/Background.jpg"))));
} catch (IOException e) {
e.printStackTrace();
}
frame.setLayout(new FlowLayout());
frame.setContentPane(background);
frame.add(alarmClockButton);
frame.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
frame.setVisible(true);
frame.setSize(450, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
alarmClockButton.setForeground(Color.RED);
}
}
Thank you!
frame.setContentPane(background);
You use the label as the content pane. The problem is that the label doesn't use a layout manager by default.
You need to add:
background.setLayout( new BorderLayout() ); // or whatever layout you want
frame.setContentPane(background);
Now you can add the button directly to the frame. You don't need the panel.
Or if you want to get fancy you can use the Background Panel which gives you the option to scale or tile the background image.
Instead of making the ContentPane as JLabel, you can wrap the JLabel in a JPanel, then add this JPanel as the ContentPane :
public class MainMenu {
public static void main(String[] args) {
new MainMenu();
}
// JFrame = the actual menu / frame.
private JFrame frame;
private JPanel panel;
private JPanel bkgPanel;
// JLabel = provides text instructions or information on a GUI —
// display a single line of read-only text, an image or both text and an
// image.
private JLabel background;
// JButton = button.
private JButton alarmClockButton;
// Constructor to create menu
public MainMenu() {
frame = new JFrame("Alarm Clock");
panel = new JPanel();
bkgPanel = new JPanel();
alarmClockButton = new JButton("Timer");
// Add an event to clicking the button.
alarmClockButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// TODO: CHANGE TO SOMETHING NICER
JOptionPane.showMessageDialog(null, "This feature hasn't been implemented yet.", "We're sorry!",
JOptionPane.ERROR_MESSAGE);
}
});
// Creating the background
try {
background = new JLabel(new ImageIcon(
ImageIO.read(getClass().getResourceAsStream("/me/devy/alarm/clock/resources/Background.jpg"))));
bkgPanel.add(background);
} catch (IOException e) {
e.printStackTrace();
}
frame.setContentPane(bkgPanel);
frame.add(panel);
panel.add(alarmClockButton);
frame.setVisible(true);
frame.setSize(450, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
alarmClockButton.setForeground(Color.RED);
}
}

Image Icon not displaying in JPanel

Code is pretty simple. I get a URL string from an arraylist. I am then trying to draw an image in my JPanel. If I don't initialize a layout in the code, it returns an error. If I do initialize a layout, there's no error, but the icon doesn't display either. Am I missing something? Thank you!
public class CharacterPage extends JFrame {
private JPanel imagesPanel;
private WikiDB wikiDB;
public CharacterPage(WikiDB db) throws IOException {
super("Character Page");
setContentPane(rootPanel);
pack();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
setSize(new Dimension(500,500));
imagesPanel.setLayout(new BorderLayout());
this.wikiDB = db;
searchButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
ArrayList<String> characterImages =
wikiDB.searchImages(characterID);
//array contains this string: http://cosplayidol.otakuhouse.com/wp-content/uploads/2012/06/s-1-1.jpg
for (int x = 0; x < characterImages.size(); x++){
String imageURL = characterImages.get(x);
Graphics g = getGraphics();
try {
URL url = new URL(imageURL);
//icon.paintIcon(imagesPanel,g,300,100);
JLabel wIcon = new JLabel(new ImageIcon(url));
imagesPanel.setVisible(true);
imagesPanel.add(wIcon);
} catch (MalformedURLException mue){
mue.printStackTrace();
}
}
});
}
Below is a separate program I used to read my URL. Using the code below, I can read my URL without returning any errors, but it still doesn't display in the GUI.
public class SimpleGUI extends JFrame {
private JPanel imagesPanel;
public SimpleGUI() throws IOException {
super("GUI Page");
setContentPane(imagesPanel);
pack();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setVisible(true);
setSize(new Dimension(500, 500));
imagesPanel.setLayout(new GridLayout());
BufferedImage img1 = null;
try
{
URL url1 = new URL("http://cosplayidol.otakuhouse.com/wp-content/uploads/2012/06/s-1-1.jpg");
URLConnection conn1 = url1.openConnection();
conn1.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
InputStream in1 = conn1.getInputStream();
img1 = ImageIO.read(in1);
} catch (IOException e)
{
e.printStackTrace();
}
JLabel wIcon = new JLabel(new ImageIcon(img1));
imagesPanel.add(wIcon);
}
}
EDIT: I am getting closer in that I can now pop up a separate frame containing the picture using this code:
public class SimpleGUI extends JFrame {
private JPanel imagesPanel;
private JFrame mainFrame;
public SimpleGUI() throws IOException {
super("GUI Page");
setContentPane(imagesPanel);
pack();
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setSize(new Dimension(500, 500));
mainFrame = new JFrame();
imagesPanel.setLayout(new GridLayout());
imagesPanel.setBounds(0,0,200,200);
mainFrame.add(imagesPanel);
mainFrame.setVisible(true);
I can't seem to find the original frame in my GUI form, so I can add the imagesPanel to that instead. I am using IntelliJ's GUI form builder.
One problem, you're trying to add multiple components to a BorderLayout using JPanel from within a for loop and by doing this, you'll over-write all that was added before with anything added new. Use a much more appropriate layout such as a GridLayout instead.
Another problem, where do you add the imagesPanel to anything? Calling setVisible(true) on it will do nothing of use, but adding it to the JFrame or to a JPanel that is ultimately held by the JFrame will do a lot.
Also, you need to do some serious debugging usually before coming here -- does your reading in of the image work at all? Create a simple GUI, one that reads in the Image (use ImageIO.read(URL url) for this), creates an ImageIcon and displays the Icon in a JOptionPane. If this works, then the problem is elsewhere. If it doesn't then work on correcting the URL address.

JFrame removing JPanels and adding a new JPanel

I currrently have a SwingWorker that sends a HTTP Request and I override the SwingWorker's done() method to change contents in a JFrame. I want to basically remove everything and add a new members panel on the JFrame depending on the values returned from the Server.
Now, the problem I am facing is that when I invoke the following methods below on the JFrame, it doesn't remove anything from the JFrame nor does it change it's contents contained within the Frame.
//TODO: Investigate why JFrame content pane won't repaint.
f.removeAll();
//Pass the frame f reference only into MainDisplay, it doesn't actually do anything apart from allowing a class to add a JMenuBar on the JFrame.
f.add(new MainDisplay(f));
f.getContentPane().invalidate();
f.getContentPane().validate();
f.getContentPane().repaint();
The current fix I have is this below but I would rather change the contents of the JFrame rather then loading a new one up.
f.dispose();
f=new ApplicationFrame();
I've looked through previous answers on here and on Google and some state use validate() or invalidate() whilst calling repaint() to repaint the JFrame.
Any suggestions/help would be much appreciated.
Edit: I think I am going to debug more since there must be something else going wrong.
for example
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class MyFrame extends JFrame {
private static final long serialVersionUID = 1L;
public MyFrame() {
final JPanel parentPanel = new JPanel();
parentPanel.setLayout(new BorderLayout(10, 10));
final JPanel childPanel1 = new JPanel();
childPanel1.setBackground(Color.red);
childPanel1.setPreferredSize(new Dimension(300, 40));
final JPanel childPanel2 = new JPanel();
childPanel2.setBackground(Color.blue);
childPanel2.setPreferredSize(new Dimension(800, 600));
JButton myButton = new JButton("Add Component ");
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
parentPanel.remove(childPanel1);
parentPanel.add(childPanel2, BorderLayout.CENTER);
parentPanel.revalidate();
parentPanel.repaint();
pack();
}
});
setTitle("My Empty Frame");
setLocation(10, 200);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
parentPanel.add(childPanel1, BorderLayout.CENTER);
parentPanel.add(myButton, BorderLayout.SOUTH);
add(parentPanel);
pack();
setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
MyFrame myFrame = new MyFrame();
}
});
}
}
You are trying to repaint()/validate() the ContentPane. Did you try doing same on the JFrame?
You can also try JFrame#pack().
modification of your code
f.setContentPane(new MainDisplay(f));
f.getContentPane().invalidate();
f.getContentPane().validate();
f.getContentPane().repaint();
You may try using Frame.pack() again it worked for me. Or try one od those following methods:
Frame.setOpaque(false);
Frame.setEnabled(false);
Frame.setVisible(false);
Frame.removeAll();

Categories