I'm having a problem that seems a little bit strange. When I'm adding a new ImageIcon and try to run the program it just gives me a gray screen and no objects are added.
public class Ctester {
public Ctester(){
Frame();
}
public void Frame(){
JFrame fr = new JFrame();
fr.setVisible(true);
fr.setSize(500, 500);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fr.setResizable(false);
JPanel p = new JPanel(new GridBagLayout());
ImageIcon icon = new ImageIcon(getClass().getResource("zippo.jpg"));
JLabel l = new JLabel(icon)
JButton bm1 = new JButton("hellu");
p.add(l);
p.add(bm1);
fr.add(p);
}
public static void main(String[]args){
new Ctester();
}
}
But if I remove the line:
ImageIcon icon = new ImageIcon(getClass.getResource("zippo.jpg"));
then it works perfect.
I'm not getting any error messages and i been looking for a while but I could only find that the problem might be something with the gridbaglayout.
How can i solve it or do I have to change layout?
(this is just a simple code based of the original as an example so any solutions that not include having to change layout is highly appreciated)
Most of the code is wrong:
Swing components should be create on the Event Dispatch Thread (EDT).
The frame should be made visible AFTER all the components have been added to the frame.
You are attempting to use a GridBagLayout, but you aren't using any GridBagConstraints when you add the components.
Method names (Frame) should NOT start with an upper case character.
Read the Swing Tutorial for Swing basics.
You can find working examples in:
How to Use GridBagLayout
How to Use Icons
so any solutions that not include having to change layout is highly appreciated
Start with the working examples and make changes for your requirements. If you start with better structured code you will have less problems.
If something draws correctly after a window resize or minimize/maximize that is a sure sign of a race condition because you are not starting your GUI on the event dispatcher thread. Your main problem is you are calling setVisible() way to early, don't call setVisible() until after you have added all components to your top-level container. The other problem is you are not starting your GUI on the event dispatcher thread. Please see the main method below in the fixed code:
public class Ctester {
public Ctester() {
Frame();
}
public void Frame() {
JFrame fr = new JFrame();
fr.setSize(500, 500);
fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
fr.setResizable(false);
JPanel p = new JPanel(new GridBagLayout());
JLabel l = new JLabel("label");
JButton bm1 = new JButton("hellu");
p.add(l);
p.add(bm1);
fr.add(p);
fr.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
new Ctester();
}
});
}
}
Try this code you might want to put that first line of code in a try catch just in case that it doesn't find the image.
URL iconURL = getClass().getResource("/some/package/favicon.png");
// iconURL is null when not found
ImageIcon icon = new ImageIcon(iconURL);
fr.setIconImage(icon.getImage());
Also use a .ico file if you are only using this program on Windows but use a .png if it is going to be multi-platform
Related
I am trying to write an application that get video frames, process them and then display them in JPanel as images. I use the OpenCV library to get video frames (one by one), then they are processed and after that displayed on the screen (to get the effect of playing video).
I created the GUI using Java Swing. A window application is created with the necessary buttons and a panel to display the video. After clicking "START", a method playVideo is called, which takes video frames from the selected video, modifies them and displays them in the panel. My code looks like this:
public class HelloApp {
private JFrame frame;
private JPanel panel;
final JLabel vidpanel1;
ImageIcon image;
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
HelloApp window = new HelloApp();
window.frame.setVisible(true);
}
});
}
public void playVideo() throws InterruptedException{
Mat inFrame = new Mat();
VideoCapture camera = new VideoCapture();
camera.open(Config.filename);
while (true) {
if (!camera.read(inFrame))
break;
Imgproc.resize(inFrame, inFrame, new Size(Config.FRAME_WIDTH, Config.FRAME_HEIGHT), 0., 0., Imgproc.INTER_LINEAR);
... processing frame
ImageIcon image = new ImageIcon(Functions.Mat2bufferedImage(inFrame)); // option 0
vidpanel1.setIcon(image);
vidpanel1.repaint();
}
}
public HelloApp() {
frame = new JFrame("MULTIPLE-TARGET TRACKING");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(null);//new FlowLayout()
frame.setResizable(false);
frame.setBounds(50, 50, 800, 500);
frame.setLocation(
(3 / 4) * Toolkit.getDefaultToolkit().getScreenSize().width,
(3 / 4) * Toolkit.getDefaultToolkit().getScreenSize().height
);
frame.setVisible(true);
vidpanel1 = new JLabel();
panel = new JPanel();
panel.setBounds(11, 39, 593, 371);
panel.add(vidpanel1);
frame.getContentPane().add(panel);
JButton btnStart = new JButton("START / REPLAY");
btnStart.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
playVideo();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
});
}
}
I tried to delete the old panel and create a new one every time when button "START" is clicked, but it didn't work. Also I tried before running method playVideo to clean all the panel with methods:
panel.removeAll();
panel.repaint();
playVideo();
And to be honest I don't know what's wrong. The GUI is created, frames are taken and processed, but the panel displays only the last frame. I would be grateful for any advice :)
First of all, a proof it can actually work, somehow, with your code.
Here I read JPG images located in the resources folder, but it actually doesn't really matter.
Your code is a bit messy too. Where are you attaching the btnStart JButton to the outer panel? You need to understand how to layout components too.
You have a main JFrame, and a root JPanel which needs a layout. In this case we can opt for a BorderLayout.
panel = new JPanel(new BorderLayout());
Then we add our components.
panel.add(btnStart, BorderLayout.PAGE_START);
panel.add(vidpanel1, BorderLayout.CENTER);
Now coming to your issue, you say
The gui is created, frames are taken and processed, but panel display only the last frame
I don't know how much the "last frame" part is true, mostly because you're running an infinite - blocking - loop inside the Event Dispatch Thread, which will cause the GUI to freeze and become unresponsive.
In actionPerformed you should actually spawn a new Thread, and inside playVideo you should wrap
ImageIcon image = new ImageIcon(Functions.Mat2bufferedImage(inFrame));
vidpanel1.setIcon(image);
vidpanel1.repaint(); // Remove this
in EventQueue.invokeAndWait, such as
// Process frame
...
// Update GUI
EventQueue.invokeAndWait(() -> {
ImageIcon image = new ImageIcon(Functions.Mat2bufferedImage(inFrame));
vidpanel1.setIcon(image);
});
I have a JFrame and I want to add a JPanel with a JButton. But all the guides in the internet seem to be wrong. If I follow these instructions my buttons will not be shown.
I know that there are questions similar to mine, but these posts have too much code instead of the problem in an isolated code. So I cannot figure out from it what their solution is.
public class MainClass {
public static void main (String[]args) {
Frame frame = new Frame();
}
}
public class Frame extends JFrame {
private JButton btn;
private JPanel pnl = new JPanel();
Frame () {
setSize(400,400);
setLayout(new FlowLayout());
setVisible(true);
setButtons();
add(pnl);
}
private void setButtons() {
btn = new JButton();
pnl.add(btn);
}
}
setVisible(true);
setButtons();
add(pnl);
Your components have a size of (0, 0) so there is nothing to paint.
The solution is to make the frame visible AFTER all the components have been added to the frame:
setButtons();
add(pnl);
setVisible(true);
When you make the frame visible, or use the pack(), method the layout manager is invoked so know the components will have a size/location.
but these posts have too much code instead of the problem in an isolated code.
I suggest you start with the code example from the Swing Tutorial for Swing basics. Download an example and use it as a starting point for a better structured class. For example all Swing components should be create on the Event Dispatch Thread (EDT).
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().
I have a single JLabel in my JFrame, initially displayed using pack().
My problem is that whenever I try to resize the window, the JLabel also moves (depending on which side of the window is resized), largely due to the layout of the JFrame.
To be more specific, whenever I resize the window up/down, the JLabel stays centered. I would like that not be the case.
I'm sorry if my question is confusing. I'll gladly provide diagrams if requested.
public class JavaApplication8 {
public static void main(String[] args) throws MalformedURLException {
// TODO code application logic here
JFrame window = new JFrame("test");
URL bgURL = new URL("https://si0.twimg.com/profile_images/3585146044/3b695fa73490227f792fa4e46d4a7a57.jpeg");
ImageIcon bg = new ImageIcon(bgURL);
JLabel label = new JLabel(bg);
window.add(label, BorderLayout.CENTER);
window.pack();
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}
Use a different layout manager:
window.setLayout(new FlowLayout());
would be sufficient for the example.
Another possibility, if you want to keep using BorderLayout, is placing the label to a different position:
window.add(label, BorderLayout.NORTH);
Also note that you should access swing components only from the event dispatch thread.
I have written the following example code:
import org.jdesktop.swingx.*;
import javax.swing.*;
import java.awt.*;
public class TaskPaneExample{
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
new TaskPaneExample();
}});
}
public TaskPaneExample() {
JFrame frame = new JFrame("TaskPane Example 1");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(doInit(), BorderLayout.CENTER);
frame.setLocationRelativeTo(null);
frame.pack();
frame.setVisible(true);
}
private Component doInit() {
JXTaskPaneContainer taskpanecontainer = new JXTaskPaneContainer();
taskpanecontainer.setLayout(new VerticalLayout(2));
final JXTaskPane taskpane1 = new JXTaskPane(){
public void setCollapsed(boolean w){
super.setCollapsed(w);
}};
taskpane1.setTitle("First TaskPane");
JPanel panel1 = new JPanel();
panel1.setBackground(Color.red);
panel1.setSize(100,100);
taskpane1.add(panel1);
taskpanecontainer.add(taskpane1);
JXTaskPane taskpane2 = new JXTaskPane(){
public void setCollapsed(boolean w){
super.setCollapsed(w);
}};
taskpane2.setTitle("My Tasks");
JPanel panel2 = new JPanel();
panel2.setBackground(Color.blue);
panel2.setSize(100,100);
taskpane2.add(panel2);
taskpanecontainer.add(taskpane2);
taskpanecontainer.setBorder(javax.swing.BorderFactory.createEmptyBorder(0, 0, 0, 0));
return taskpanecontainer;
}
}
}
What I need are two things:
how do I change the bgcolor of the title? I think it is done with the taskpane2.setUI(..) option but I had no luck working with it.
how to set the border between the JXTaskPane and the Jpanel to zero?
Originally, the JXTaskPane was designed as a kind of "fixed-properties" component - it should look exactly like the corresponding native component (then of WinXP): custom appearance wasn't meant to be supported. As a consequence, the implementation of the title/border is deeply hidden in the XXTaskPaneUI - actually, everything boils down to be a Border.
1) as dogbane already mentioned, some of the properties can be changed on a per-application basis. Just beware: those are implementation details which might change or not be supported by concrete ui implementations (Nimbus is always a good candidate to not respecting them, even our not-really-synth implementation might not, forgot)
2) the "gap" is the border of the contentPane, you can set your own. Again a beware: might not survive an updateUI (could be that the ui delegates override them unconditionally, if so, please file an issue in the SwingX issuetracker)
((JComponent) taskpane2.getContentPane()).setBorder(BorderFactory.createEmptyBorder());
BTW: those panel.setSize have exactly no effect - layoutManagers rule ;-)
To change the bgcolour of the title, you can try setting the start and end background gradient colours in the UIManager:
UIManager.put("TaskPane.titleBackgroundGradientStart", Colors.White.color());
UIManager.put("TaskPane.titleBackgroundGradientEnd", Color.GREEN);
I also found an open swingx jira task for this: SWINGX-731 Support to define the color to JXTaskPane header.