Displaying an image, Java - java

I'm new to Java GUI, and am having issues displaying an image. My intention is to display a large image and allow the user to click on regions of the image to indicate where certain features are located. Anyway, I'm getting a rough start because I can't even get the image to appear, despite reading Oracle's explanation and other solutions.
I've created a JFrame and used its setContentPane() method to add a JPanel and JLabel. I use the setIcon() method of the JLabel to add an image to it, or at least that's my intention...
Any advice is appreciated, especially if there's a better way of doing this. I'll be using OpenCV to process images, and plan to convert them to Java image (or BufferedImage) before displaying them.
Here is the code. I left out the libraries to save space.
public class Pathology {
public static void main(String[] args) {
PrimaryFrame primaryFrame = new PrimaryFrame();
primaryFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
primaryFrame.setSize(1500, 900);
primaryFrame.setVisible( true );
primaryFrame.setContentPane(primaryFrame.getGui());
try {
primaryFrame.setImage(ImageIO.read(new File("C:\\Users\\Benjamin\\Pictures\\Pathology\\C\\001.png")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
GUI Class:
public class PrimaryFrame extends JFrame{
//private JTextField textField1;
JPanel gui;
JLabel imageCanvas;
public PrimaryFrame() {
super( "Pathology-1" );
//setLayout(new FlowLayout());
//textField1 = new JTextField("Chup!", 50);
//add(textField1);
}
public void setImage(Image image) {
imageCanvas.setIcon(new ImageIcon(image));
}
public void initComponents() {
if (gui==null) {
gui = new JPanel(new BorderLayout());
gui.setBorder(new EmptyBorder(5,5,5,5));
imageCanvas = new JLabel();
JPanel imageCenter = new JPanel(new GridBagLayout());
imageCenter.add(imageCanvas);
JScrollPane imageScroll = new JScrollPane(imageCenter);
imageScroll.setPreferredSize(new Dimension(300,100));
gui.add(imageScroll, BorderLayout.CENTER);
}
}
public Container getGui() {
initComponents();
return gui;
}
}

Would you laugh at me if I'd tell you that you just have to put the primaryFrame.setVisible( true ); to the end of the main method? :)
For furture understanding, you don't have to call frame.setVisible(true) every time you want to add/update something in the frame (in an ActionListener, for example). Instead you can call frame.revalidate() and frame.repaint(). (Where frame can be replaced with the particular panel)

You need to setVisible(true) after the call to setImage():
primaryFrame.setImage(ImageIO.read(new
File("C:\\Users\\Benjamin\\Pictures\\Pathology\\C\\001.png")));
because any update to the GUI after setVisible() will not be shown.
That's it and the code should be like this:
public class Pathology {
public static void main(String[] args) {
PrimaryFrame primaryFrame = new PrimaryFrame();
primaryFrame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);
primaryFrame.setSize(1500, 900);
primaryFrame.setContentPane(primaryFrame.getGui());
try {
primaryFrame.setImage(ImageIO.read(new File(
"C:\\Users\\Benjamin\\Pictures\\Pathology\\C\\001.png")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
primaryFrame.setVisible( true );
}
}

Related

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);
}
}

a button that takes to a new panel

I created a button that is in the main page which when a user clicks on it، it changes the panal ( the main idea is that it changes the background and all whats on the panel and adds new stuff to it ) however i failed!, i also failed in adjusting the location of the button although i tried button.setBounse(..)
anyhow can someone help me in those two things?
public class mainClass {
private static JButton start;
static BackgroundPanel bp = null;
static JFrame mainf = null;
public static void main(String[] args) throws IOException {
mainf = new JFrame ("سين جيم");
// background
BufferedImage mFrame = ImageIO.read(new File("B1.png"));
bp = new BackgroundPanel(mFrame);
mainf.add(bp);
bp.setLayout(new GridBagLayout());
// Hi string
JLabel hi = new JLabel ("أهلا وسهلا");
Font fs = hi.getFont();
hi.setFont(fs.deriveFont(50f));
bp.add(hi);
// button
JPanel another = new JPanel();
start = new JButton ( " لنبدأ");
bp.add(start);
start.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
bp.removeAll();
BufferedImage mFrame2= null;
try {
mFrame2 = ImageIO.read(new File("B2.png"));
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
bp = new BackgroundPanel(mFrame2);
bp.setLayout(new GridBagLayout());
JLabel hi1= new JLabel ("worked");
bp.add(hi1);
}
} );
// end of frame
mainf.pack();
mainf.setVisible(true);
}
}
Well, to change your main panel you don't have to create a new Frame object and set it's main panel. E.g., you could write a setter for bp and invoke this method in your action listener method. If your panel has a different size, you can easily change the frame's size...

JButton is only appearing on MouseOver

I've tried multiple things but I can't seem to figure out how to get my JButton over the background graphics. Does anybody know how I can paint over this background and have my button stay there? I would paste the code here but It would get a little messy, so heres some pastebin links!
Main class: http://pastebin.com/DvVfCU03
MenuPanel class: http://pastebin.com/uht8cabX
Here's a copy of the main class just in-case:
public class Main
{
final static JFrame window = new JFrame();
final static ImageIcon imageIconOne = new ImageIcon(getConnectImage());
final static JButton connectB = new JButton(imageIconOne);
public static void main(String[] args) throws IOException
{
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setContentPane(new MenuPanel());
window.addKeyListener(new MenuPanel());
window.setMinimumSize(new Dimension(1024, 640));
window.pack();
window.setTitle("Realm of Pixels");
window.setVisible(true);
window.addMouseListener(new MouseHandler());
window.setVisible(true);
window.add(connectB);
}
public static Image getConnectImage()
{
Image connectImage = null;
try
{
connectImage = ImageIO.read(new File("Resources/Buttons/Connect.png"));
}
catch (IOException e)
{
e.printStackTrace();
}
return connectImage;
}
public static JFrame getWindow()
{
return window;
}
}
I maybe wrong but,
shouldn't you be making the button visible too? Something like...
connectDB.setVisible(true);
Or to see if the button has been added to the window you could temporarily set the button to opaque.

java.awt.Container.checkNotAWindow error in simple gui

I am trying to draw a simple GUI (created with windowbuilder in eclipse), I want to have 2 buttons and a scrollable text area between them. I have created the following code to achieve the above:
public class Main extends JFrame implements ActionListener{
public Font font; //used for the font file
public JTextArea txtDataWillBe;
public Main() throws FontFormatException, IOException{
setTitle("Main title ");
setBounds(100, 100, 1200, 600);
getContentPane().setLayout(null);
txtDataWillBe = new JTextArea();
txtDataWillBe.setText("Your data will display here");
txtDataWillBe.setFont(new Font("Droid Sans", Font.BOLD, 18));
txtDataWillBe.setEditable(false);
txtDataWillBe.setColumns(1);
txtDataWillBe.setBounds(0, 40, 919, 484);
getContentPane().add(txtDataWillBe);
JButton button = new JButton("CLICK TO OPEN");
button.setBounds(0, 0, 940, 40);
button.setFont(new Font("Coalition", Font.PLAIN, 18));
getContentPane().add(button);
JButton btnPrint = new JButton("PRINT");
btnPrint.setBounds(0, 531, 940, 40);
btnPrint.setFont(new Font("Coalition", Font.PLAIN, 18));
getContentPane().add(btnPrint);
}
private final String JTextFile = null;
JFileChooser chooser;
String choosertitle;
public static File deletefile;
EDIT:
public static void main(String s[]) {
JFrame frame = new JFrame("Reader");
Main panel = null;
try {
panel = new Main();
} catch (FontFormatException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
File deleteme = new File (deletefile + "mx.txt");
deleteme.delete();
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(panel.getPreferredSize());
frame.setVisible(true);
}
I originally had the JTextarea inside of a JScrollPane (thinking that was the best way to get the scrolling I want working). I removed the JScrollPane thinking that was causing the console error, but I am still getting the error.
Console output is:
Exception in thread "main" java.lang.IllegalArgumentException: adding a window to a container
at java.awt.Container.checkNotAWindow(Container.java:439)
at java.awt.Container.addImpl(Container.java:1035)
at java.awt.Container.add(Container.java:923)
EDIT: Main added above.
What I am doing wrong with my GUI?
Do I need a JScrollPane and JTextArea to enable vertical scrolling of the loaded text?
Thanks for your help;
Andy
EDIT:
I have edited as per the suggestions below so my code now reads:
public Main() throws FontFormatException, IOException{
JFrame frame = new JFrame("Reader ");
frame.addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
File deleteme = new File (deletefile + "mx.txt");
deleteme.delete();
System.exit(0);
}
}
);
frame.getContentPane().add(panel,"Center");
frame.setSize(getPreferredSize());
frame.setVisible(true);
The rest of the code is as before but all I am getting displayed is a blank grey frame without any of my components (although they are all showing in windowbuilder).
Thanks for the continued help.
The console output is describing exactly what is wrong here.
IllegalArgumentException: adding a window to a container
In the line frame.getContentPane().add(panel,"Center"); you add panel into your content pane, but panel itself is an instance of Main extends JFrame.
You should remove any reference to the outer frame at all and just add the window listener to the Main frame, i.e. the main code reduces to something like
JFrame frame = new Main();
frame.addWindowListener( ... );
frame.setVisible(true);
You may also want to move the addWindowListener part inside class Main.

User-Interface question

i'm kinda new to manipulating UI in java, so pls forgive me for this question i cant find the answer anywhere.
Description
| i'm trying to do a card game and i have an engine class that manipulates all the cards and plays made, and i want the engine to tell the UI to update the score, card position or card image.
this is an example of how i start the UI, problem here is i don't have any instance to manipulate the JLabels using the instance methods i made inside Board class, and i can't create a instance outside of the EventQueue because i would be violating "never manipulate/create UI outside UI thread"
public class Engine {
public StartUp(){
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
} catch (UnsupportedLookAndFeelException e) {
}
new Board().setVisible(true);
}
});
}
}
the Board class extends JPanel and adds some JLabels to the ui in the constructor , and has several methods to change text and imgs.
My question is how to properly call these methods(the ones i created to alter text and img), i'm also open o any other suggestions on how to approach this problem.
*edited:
here's simple example of my Board Class:
public class Board extends JFrame{
public JLabel img1;
public Board(){
setDefaultCloseOperation(EXIT_ON_CLOSE);
setSize(400, 265);
JPanel body = new JPanel(new GridBagLayout());
getContentPane().add(body);
img1 = new JLabel();
body.add(img1);
}
public void setImg1(String s){
img1.setIcon(new ImageIcon(s));
}
}
i want to be able from Engine to access setImg1(String s) method that is inside the Board to be able to change the current image during runtime
sorry if i expressed my question wrong
final edit:
solved it merging the Engine into the Board.
ty to everyone that helped and for your time
public class MainFrame extends JFrame {
public MainFrame() {
super("Demo frame");
// set layout
// add any components
add(new Board()); // adding your board component class
frameOptions();
}
private void frameOptions() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
pack(); // or setSize()
setVisible(true);
}
public static void main(String[] a) {
JFrame.setDefaultLookAndFeelDecorated(true);
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(
UIManager.getSystemLookAndFeelClassName());
new MainFrame();
} catch (Exception exp) {
exp.printStackTrace();
}
}
});
}
}
The basic idiom for getting a GUI up is:
SwingUtilities.invokeLater(new Runnable() {
JFrame frame = new JFrame("My Window Title");
frame.setSize(...);
frame.add(new Board()); // BorderLayout.CENTER by default
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null); // center on main screen
frame.setVisible(true);
});

Categories