What is wrong with this method for displaying images? - java

I am very confused. Why would this method not work for displaying an image:
private void showImage(final BufferedImage image){
SwingUtilities.invokeLater(
new Runnable(){
#Override
public void run(){
ImageIcon icon = new ImageIcon(image);
JLabel label = new JLabel();
label.setIcon(icon);
add(label, BorderLayout.CENTER);
}
}
);
}
My class extends JFrame, so that's why I'm not doing something like:
frame.add(label);
I am very confused. I have tried this without the whole SwingUtilities thing and also I have tried label.setVisible(true)
What the heck am I doing wrong here? When I run it I know this method is being called with a completely okay BufferedImage (I had it output something in the method). I expected a JLabel to come up with my image on it, but just the JFrame came up, no image in sight.

add(label, BorderLayout.CENTER);
When you add (or remove) a component from a visible GUI the basic code is:
panel.add(...);
panel.revalidate();
panel.repaint();
In your case you would revidate the frame since you are adding the label to the content pane of the frame.
That is you need to invoke the layout manager, otherwise the component has a size of (0, 0) so there is nothing to paint.
However, a better solution would probably be to add the label to the GUI when you create the frame.
Then to change the icon you just do:
label.setIcon(...);
No need to create a new JLabel every time you want to change the image.

Related

Setting Background of a JTextPane leads to visual artifacts (Java)

this is my first question on stackoverflow so pls don't be so hard with me (and my English), I'll try my best asking a good question.
The problem is about what the title suggests -> setting the background of a JTextpane (specifically setting it transparent). As the setBackground-method takes a color argument, the way i went was with an alpha value = 0. This leads to the following visual artifacts:
example picture of the visual artifacts when running the code below
I will describe it in detail now, say what i've already tried and then post a minimal example for everyone to be able to recreate the bug easily.
I have a JFrame (myFrame) holding a JPanel (Test()) in which i paint. The background of this JPanel is set to green as you can see in the code. I did this to differ between the background of the TextPane and the actual background of the panel.
We also have a JTextPane inputfield -> which takes user input (it displays what you write). This is held by a JScrollPane scrollpane.
So the Target (meaning what i try to achieve): is a User input field, which is transparent, but still displays the text the user puts in. I tried to achieve this by setting the background of the inputfield and the scrollpane to a transparent color.
I would really appreciate it, if you don't just type something like (you need to setOpague(false) for ....) if you don't know exactly what you're talking about, because i nearly tried everything i can think of and read every post i could find in the internet about the problem. I will post some of them at the end. So...
What i already tried:
The usual way i found while searching for something like "How to make TextPane transparent" was to setOpague(false) at itself as well as the scrollpane and the viewport of the scrollpane. 1. Reading about what the method actually does i don't think that is a proper solution. 2. setting Opague(false) on these three leads to everything being invisible so, that's not good. Packing the frame again after setting the background. Either nothing was fixed or the components became completely invisible.
I also tried: setBackground(null), setting the Background of just the inputfield (just every single component and every possible combination amongst the three (scrollpane, viewport, inputfield)), mixing setOpague(true)/setOpague(false)/setBackground(...) in every way i could think of. Overriding the paintComponent method of the textpane and scrollpane seemed like a good approach, but i did not come very far with it.
So here is the code:
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
#Override
public void paint(Graphics g) {
super.paint(g);
inputField.setBounds(10,10,100,100);
scrollpane.setBounds(10,10,100,100);
}
public Test(){
this.setOpaque(true);
this.setBackground(Color.GREEN);
inputField.setBounds(10,10,100,100);
scrollpane.setBounds(10,10,100,100);
inputField.setBackground(new Color(0,0,0,0));
scrollpane.setBackground(new Color(0,0,0,0));
scrollpane.getViewport().setBackground(new Color(0,0,0,0));
this.add(scrollpane);
}
public static void main(String[] args) {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.pack();
myFrame.setSize(640,480);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.setVisible(true);
}
}
And here some links to posts I read which describe similar problems:
Java - Transparent JScrollPane
Transparent JEditorPane in a JScrollPane over a background JPanel
setOpaque(true/false); Java
I would really appreciate if someone can help me with the problem or even only suggest me an alternative solution. I'm writing a little chat-program atm for a project for my university and i think transparent message fields are a neat idea. I will try to answer here as fast as i can. Thx in advance.
Do not use transparent color as background - kind of hard to delete with it (e.g. when component is being repaint (and opaque)).
Do not use setBounds (unless using null LayoutManager). In below example I used setPreferredSize but still better to correctly use LayoutManager (I am a bit lazy, and lot of work to do at the moment).
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
public Test(){
this.setOpaque(true);
this.setBackground(Color.GREEN);
inputField.setPreferredSize(new Dimension(300, 100));
inputField.setOpaque(false);
scrollpane.setOpaque(false);
scrollpane.getViewport().setOpaque(false);
this.add(scrollpane);
}
public static void main(String[] args) {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.pack();
myFrame.setVisible(true);
}
}
The whole code of main should be called on the EDT (e.g. SwingUtilities.invokeLater) since it is manipulating swing components but that is not part of the question (and not that relevant here since setVisible is the last command - components not being displayed while changed).
Your program gave me some errors when launching, occasionally. Make sure to run a swing GUI from the EDT (invokeLater()).
The line that is causing your issue is:
scrollpane.getViewport().setBackground(new Color(0,0,0,0));
Also - is there some reason you are setting bounds manually instead of using a layout manager?
Maybe I didn't understand your question, or you want to have an image in the background - but could you not just set the color of your text area to be the same color as your JPanel?
import java.awt.Color;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
public class Test extends JPanel {
JTextPane inputField = new JTextPane();
JScrollPane scrollpane = new JScrollPane(inputField);
public Test(){
this.setBackground(Color.GREEN);
scrollpane.setPreferredSize(new Dimension(300, 300));
inputField.setBackground(Color.GREEN);
this.add(scrollpane);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame myFrame = new JFrame();
myFrame.add(new Test());
myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
myFrame.setPreferredSize(new Dimension(640,480));
myFrame.pack();
myFrame.setVisible(true);
}
});
}
}

Dynamically Add Image To JLabel [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I am attempting to dynamically add an image to my JLabel then add the JLabel to my panel. My code is throwing no errors, but the image is never shown.
public JFrameGamePlay(String playername, String playerselected) {
initComponents();
playerimage = "/Users/owner/Downloads/__Pikachu.png";
ImageIcon pimage = new ImageIcon(playerimage);
JLabel lblPlayer = new JLabel(pimage);
pnlPlayer.add(lblPlayer);
pnlPlayer.validate();
pnlPlayer.repaint();
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new JFrameGamePlay().setVisible(true);
}
});
}
EDIT
So from further googling I came up with this syntax
JLabel lblPlayer;
lblPlayer = new JLabel(new ImageIcon(getClass().getClassLoader().getResource("__Image1.png")));
pnlPlayer.add(lblPlayer);
pnlPlayer.validate();
pnlPlayer.repaint();
but when I run the code I get this debug error:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at javax.swing.ImageIcon.<init>(ImageIcon.java:217)
This is the GUI layout of how I want my data to appear - it is 1 panel on the left and 1 panel on the right - each with a label dynamically created and populated with an image. But no image is being populated.
EDIT 2
I added a black border around my 2 Panels, and when the JForm is loaded neither panel is being displayed. So it seems that what everyone is telling me that GUI designing in NetBeans is pretty buggy. How can I dynamically in my code behind add the two panels one left and one right with a size of 143, 246?
EDIT 3
Still no mustard and I'm using this syntax:
public JFrameGamePlay() {
initComponents();
JPanel leftpanel = new JPanel();
JPanel rightpanel = new JPanel();
JSplitPane pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, leftpanel, rightpanel);
JLabel lblPlayer = new JLabel(new ImageIcon("/resources/__Image1.png"));
leftpanel.add(lblPlayer);
leftpanel.validate();
leftpanel.repaint();
}
Use ImageIO.read(File) to read the Image. Like,
File playerimage = new File("/Users/owner/Downloads/__Pikachu.png");
ImageIcon pimage = new ImageIcon(ImageIO.read(playerimage));
JLabel lblPlayer = new JLabel(pimage);
pnlPlayer.add(lblPlayer);
The NullPointerException comes from the getResource("__Image1.png") returning null because it didn't find the file. You should prefix it with the location from the classpath (after all, the ClassLoader loads the file). E.g. if the image is in a res directory in your jar (or in your classpath):
JFrameGamePlay.class.getClassLoader().getResource("/res/__Image1.png")));
Or you can directly give a complete path:
new JLabel(new ImageIcon("/images/thewall.png"));
Example:
public class JFrameGamePlay extends JFrame {
private static final long serialVersionUID = 1L;
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(100, 100, 450, 300);
JPanel contentPane = new JPanel(new BorderLayout());
frame.setContentPane(contentPane);
JLabel label = new JLabel(new ImageIcon("/images/thewall.png"));
contentPane.add(label, BorderLayout.CENTER);
JLabel label1 = new JLabel(new ImageIcon(JFrameGamePlay.class.getResource("/javax/swing/plaf/basic/icons/JavaCup16.png")));
contentPane.add(label1, BorderLayout.NORTH);
frame.setVisible(true);
}
}
My code is throwing no errors, but the image is never added.
Yes, this is unfortunately how ImageIcon works. It doesn't throw exceptions or anything if it's unable to read from the filename or URL you pass to it. The code runs without error but simply shows nothing.
playerimage = "/Users/owner/Downloads/__Pikachu.png";
If you want to read from a file at a fixed location like this, then it won't be helpful to mess with getClassLoader().getResource(). That could be helpful to read an image file that you package with your application, but not to read an image in the user's home directory. Your original new ImageIcon(imageLocation) approach is appropriate for that.
[note: I think it's a good idea to send the filename (or URL) directly to the ImageIcon, as your original code does. Other answers suggest ImageIO.read(), which can be helpful to see where it's going wrong, but you could change it back to ImageIcon(filenameOrUrl) once you get it working. But it's not a big deal.]
I am attempting to dynamically add an image to my JLabel then add the JLabel to my panel.
If by "dynamically" you mean to do this when some event occurs, after the panel is already visible on the screen, then I suggest not doing that.
That is, instead of doing this...
JLabel lblPlayer = new JLabel(pimage);
pnlPlayer.add(lblPlayer);
pnlPlayer.validate();
pnlPlayer.repaint();
...you could add the JLabel to your panel (invisible because no text or image) at the very start, before your panel is shown on screen. Then dynamically add the ImageIcon to the already-extant JLabel. All you need to call is existingLabel.setIcon(...). There would be no need to call validate() or repaint().

Java JComponents being cut off near edge of JFrame

I have recently begun working with JComponents to create GUI systems. Everything is working but the bottom and right sides of the JFrame do not get painted over and remain white.
Screenshot of running GUI:
In the screenshot you can see the 'drknBtn' is displayed correctly; this is because I hovered over it with the mouse before taking the picture. Hovering over the buttons refreshes them and they appear as normal. Due to this, I would assume the panel that holds them, 'bottomPnl' is covering that white space, but that panels background is not showing at the bottom portion. Any ideas on what could cause this? I have tried calling 'bottomPnl.repaint()' directly before calling pack(), but no change.
My code is below.
Note: For each JComponent, I created a class extending that component. This way I could set default values for the components in the constructors of these classes instead of doing each one individually. I'll list the relevant properties of the Frame and Panels.
Frame: setSize(width,height); setResizeable(false); setLocationRelativeTo(null);
Panel: setLayoutManager(from contructor); setPreferredSize(new Dimension(width,height)); same for setMinimumSize and setMaximumSize.
public Display(String title, int w, int h){
width=w;
height=h;
frame = new FrameUI(title,w,h);
//parent panel
parentPnl= new PanelUI(width,height, new FlowLayout(FlowLayout.CENTER,0,0));
parentPnl.setBackground(new Color(100,175,175));
//top panel
topPnl= new PanelUI(width,(int)(height*.15), new FlowLayout(FlowLayout.CENTER,0,0));
topPnl.setBackground(new Color(100,175,175));
chooseFileBtn = new ButtonUI("Browse...",topPnl.getWidth()/4,(int)(topPnl.getHeight()*.9),new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
fc = new FileChooserUI();
fc.setFileFilter(new FileNameExtensionFilter("Image files", ImageIO.getReaderFileSuffixes()));
int result = fc.showOpenDialog(null);
try {
if (result == JFileChooser.APPROVE_OPTION) {
picture.setIcon(new ImageIcon(ImageIO.read(fc.getSelectedFile()).getScaledInstance(picture.getWidth(),picture.getHeight(), 0)));
}
} catch (Exception iOException) {
}
}
});
//middle panel
midPnl= new PanelUI((int)(width*.85),(int)(height*.7), new FlowLayout(FlowLayout.CENTER,0,0));
midPnl.setBackground(new Color(75,125,125));
picture = new LabelUI("",midPnl.getWidth(),midPnl.getHeight());
picture.setBackground(new Color(75,125,125));
picture.setVisible(true);
picture.setOpaque(true);
picture.setIcon(null);
//bottom panel
bottomPnl= new PanelUI(width,(int)(height*.15), new FlowLayout(FlowLayout.CENTER,0,0));
bottomPnl.setBackground(new Color(100,175,175));
ltnBtn = new ButtonUI("Lighten Picture",bottomPnl.getWidth()/3,(int)(bottomPnl.getHeight()*.9),new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
}
});
ltnBtn.setBackground(Color.LIGHT_GRAY);
ltnBtn.setForeground(Color.BLACK);
drknBtn = new ButtonUI("Darken Picture",bottomPnl.getWidth()/3,(int)(bottomPnl.getHeight()*.9),new ActionListener(){
#Override
public void actionPerformed(ActionEvent e) {
}
});
drknBtn.setBackground(Color.DARK_GRAY);
drknBtn.setForeground(Color.WHITE);
//add UI Objects
topPnl.add(chooseFileBtn);
midPnl.add(picture);
bottomPnl.add(ltnBtn);
bottomPnl.add(drknBtn);
parentPnl.add(topPnl);
parentPnl.add(midPnl);
parentPnl.add(bottomPnl);
Container contentPane = frame.getContentPane();
contentPane.add(parentPnl);
frame.pack();
frame.setVisible(true);
}
}
topPnl= new PanelUI(width,(int)(height*.15), new FlowLayout(FlowLayout.CENTER,0,0));
looks to me like you are manually trying to control the size of the panels and therefore the size of the components added to your panels. Your calculations are wrong and some components aren't displayed properly. Also all your sizes are fixed at creation time and will not adjust if the size of the frame ever changes.
Don't try to control the sizes manually. Use layout managers to dynamically size components based on the properties of the component.
I fail to see why you would want a button to be 15% of the space available to the frame.
If you want the button to be larger than normal you can set extra empty space around the text of the button by using:
button.setMargin( new Insets(50, 50, 50, 50) );
Then just add the button to a panel using a FlowLayout and let the layout manager do its job.
The default layout for a frame is a BorderLayout, so you can then add the "topPnl" to the frame using:
frame.add(topPnl, BorderLayout.PAGE_START);
The other panels can then be added using:
frame.add(midPnl, BorderLayout.CENTER);
frame.add(bottomPnl, BorderLayout.PAGE_END);
This is how Swing was designed to be used with layout managers.
Read the section from the Swing tutorial on How to Use BorderLayout for more information and examples.
The main point is use methods like setMargin(...), to provide hints to the component on what their preferred size should be.
I fixed the problem by removing the 'setSize()' method in the FrameUI constructor. However, I still do not understand how you could dynamically size panels as you said while still maintaining the proportions I want for them. Thank you #camickr for the pointers, my original problem is fixed. I'll look into more javadocs and tutorials on layout managers and such.

Why the button on the JFrame with background image cannot show properly

i recently code a system homepage that include the background image. After i set the background, the button that i created cannot show properly. It just appear after i use the mouse and point to the buttons' location. Can someone teach me how to fix this problem? Your help are appreciated. The codes are as below:
public class HomePage extends JFrame{
private JPanel button = new JPanel();
private JButton time = new JButton("Bus Schedule");
private JButton reserve = new JButton("Booking");
private JButton info = new JButton("About Us");
Container con = getContentPane();
public HomePage(){
setTitle("Bus Reservation System");
setSize(650,500);
setLocation(360,100);
setVisible(true);
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBackground();
setButton();
}
public void setBackground(){
JLabel background = new JLabel(new ImageIcon("C:/User/Desktop/Assignment/bg.jpg"));
con.add(background);
background.setLayout(new FlowLayout());
con.add(button);
}
public void setButton(){
Font but = new Font("Serif" , Font.ITALIC , 20);
info.setFont(but);
time.setFont(but);
reserve.setFont(but);
button.add(info);
button.add(time);
button.add(reserve);
con.add(button);
}
After you call setVisible(true), if you perform certain actions, you must manually validate() or revalidate() your window.
It is simpler to just call setVisible() after you have initialized all of the desired settings and membership of the window.
/* setVisible(true); -- wrong place */
setResizable(false);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setBackground();
setButton();
setVisible(true); // proper place
Simple mistake (probably a typo?), you are setting the layout of the JLabel, you intended to set the layout of the Container. Do con.setLayout(new FlowLayout()); instead of background.setLayout(...)
Also, I believe your path to the file is incorrect. For testing, just put the file in the project and do a path like "bg.jpg", if that works, we can verify this. For me that works. The reason I believe this is the issue is because you specify C:/Users, but then never give the folder for the specific User. A correct path would be C:/Users/Your_name/Desktop/Assignment/bg.jpg
I don't know for sure on that path part, since I'm not on your system. However, for me, if I run your code in my eclipse, this fixes it.
edit:
One last thing, the image isn't really going to be a "background" image with the current code because it will move the buttons underneath it instead of on top of it with the FlowLayout. You may want to use a different Layout.
First of all as already noted, all components should be added to the frame BEFORE invoking setVisible(true) on the JFrame.
JLabel background = new JLabel(new ImageIcon("C:/User/Desktop/Assignment/bg.jpg"));
con.add(background);
background.setLayout(new FlowLayout());
con.add(button);
Based on the above code you are adding two components to the content pane so the hierarchy of your GUI looks like this:
- frame
- content pane
- background
- button
It seems to me you want your GUI to look like this:
- frame
- content pane
- background
- button
So your code should be:
JLabel background = new JLabel(new ImageIcon("C:/User/Desktop/Assignment/bg.jpg"));
con.add(background);
background.setLayout(new FlowLayout());
//con.add(button);
background.add( button );

Different color in header of JTable

I have encountered a problem where if I use the main method in the same java file that contains the code for the JFrame which contains a JTable, and where I set the header color to yellow, when I run it , the header will be yellow. However, if I instantiate the JFRame by calling it from other classes, the header will not be yellow but will be the default color instead. Is there any way to ensure that the color stays the same even though I instantiate the JFrame and hence JTable from other classes? Thanks alot! I will be glad to clarify things if I have not explained clearly.
Hi I am sorry for not providing code beforehand. Here it is :
EquityFrame eq= new EquityFrame(file,"Apr2012");
this.dispose();// this code is in another class of a JFrame which will call the constructor of EquityFrame class
Code of EquityFrame class
public EquityFrame(File file, String nameTab){
createAndShowGUI( file, nameTab);
}
private void createAndShowGUI(File file, String nameTab){
//create frame
JTabbedPane tabPane= new JTabbedPane();
//pre-processing
init(file,nameTab);
//adding tabs
tabPane.addTab("Proposal", makeAdminPanel());
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame jf= new JFrame("CGH Equity Program");
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLayout(new BorderLayout());
jf.add(tabPane,BorderLayout.CENTER);
int w = Toolkit.getDefaultToolkit().getScreenSize().width;
int h = Toolkit.getDefaultToolkit().getScreenSize().height;
jf.setSize(w, h);
jf.setVisible(true);
}
private JPanel makeAdminPanel(){
JPanel jp=new JPanel();
String[] column = {"Job Grade", "Job Title", "Min", "Midpoint", "Max",
"Lowest", "P10", "P25", "Median", "P65", "P75", "P90",
"Highest", "Average"};
String[][] data= getArrayOfValuesForEachJobGrade();
jp.setLayout(new BorderLayout());
JTable jt= new JTable(data,column);
JTableHeader th=jt.getTableHeader();
th.setBackground(java.awt.Color.pink);
th.setEnabled(false);
jt.setTableHeader(th);
jt.setEnabled(false);
jp.add(jt,BorderLayout.CENTER);
JScrollPane scrollPane = new JScrollPane(jt, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
scrollPane.setEnabled(false);
jp.add(scrollPane, BorderLayout.CENTER);
return jp;
}
I will first run the first java file which will create an instance of EquityFrame that will display a tabbedPane with a JTable in it. However, the GUI I get from running the EquityFrame with its own main method is different from the GUI I get from creating an instance of it in another code. If i run it using its own main method, there will be a color change in the header of the table. However, the color remains the default if I run it from the other java class.
If I run it using its main method:
http://tinypic.com/r/2r5yjdj/6
If I run it using other class to call its constructor to generate the JFrame:
http://tinypic.com/r/3523yax/6
Thanks once again for any help rendered! Hope that this sheds more light on my problem.
Be certain to change the UI property before constructing anything that relies on the new value, preferablely before starting the event dispatch thread.
UIManager.put("TableHeader.background", Color.yellow);
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Application();
}
});
Alternatively, you may be able to adapt the approach shown here in the method applyUI(); it can be invoked in the constructor, as shown, or when the system calls updateUI().
Addendum: Your first image shows a Look & Feel that supports the TableHeader.background UI property. The second image appears to be the Nimbus L&F, which does not support the property.
Is the code which set the color in the definition of your main method? If so, put it in the constructors for the JFrame or JTable instead.

Categories

Resources