So, I am working on a project which requires switching between images. The images need to be in fullscreen mode. There seem to be 2 problems that I am facing.
First is with the image switching. When I switch between images, some images appear ok when I switch. Others dont seem to show up on the screen at all. I just seem to be getting an empty frame.
Second is that the right key seems to work everytime but just for my sanity, I have put system prints. The system outs dont seem to show up on the console but it switches images in the frame(Even though, I get an empty frame sometimes).
Any suggestions/solutions would be highly appreciated.
Note about the code: The draw strings that I have are for testing purposes of the coordinates. I am using an Eyetribe, so just to show where I am looking. The drawstring seems to work perfectly.
Also, I am calling switchImage very quickly, almost 22 times in a second. Could that be an issue? Although it makes me wonder why it works for some images and not for others.
UPDATE: The problem seems to be in g.drawImage. It doesnt seem to be drawing for some images but I can't seem to figure out why thats happening.
Currently this is my code for fullscreen images.
public void showFrame(){
//jL -> JLabel
//jF -> JFrame
//jP -> Panel
jF.setTitle("Test");
jF.setUndecorated(true);
jF.setResizable(false);
jF.setVisible(true);
Toolkit tk = Toolkit.getDefaultToolkit();
int xsize = (int)tk.getScreenSize().getWidth();
int ysize = (int)tk.getScreenSize().getHeight();
jF.setSize(xsize, ysize);
jF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
if(testImagesList != null){
img = new ImageIcon(testImagesList.get(0));
}
Image imag = img.getImage();
bi = new BufferedImage(1280, 800, BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.createGraphics();
g.drawImage(imag, 0, 0, 1280, 800, null);
ImageIcon newIcon = new ImageIcon(bi);
jL.setIcon(newIcon);
jF.add(jL);
jP.add(jL);
jF.add(jP);
jF.validate();
}
To switch between images I am using a key listener. The keyListner calls the switch image code. Both are given below.
public void switchImage(ImageIcon image, JFrame jF, JLabel jL, JPanel jP, GazeData gazeData){
Image imag = image.getImage();
BufferedImage bi = new BufferedImage(1280, 800, BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.getGraphics();
g.drawImage(imag, 0, 0, 1280, 800, null);
g.setColor(Color.black);
int x = (int) gazeData.smoothedCoordinates.x;
int y = (int) gazeData.smoothedCoordinates.y;
Font font = new Font("Verdana", Font.BOLD, 16);
g.setFont(font);
String text = "hello(" + gazeData.smoothedCoordinates.x + gazeData.smoothedCoordinates.y + ")";
g.drawString(text, x, y);
g.drawString("Fixed Coordinate at (400, 500)", 400, 500);
ImageIcon newIcon = new ImageIcon(bi);
jL.setIcon(newIcon);
jP.add(jL);
jF.validate();
}
#Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
// j.switchImage(image, jF, jL, jP, gazeData);
System.out.println("RightDetected");
imageIndex++;
ImageIcon newImage = new ImageIcon(imageList.get(imageIndex));
if(newImage != null){
this.currentImage = newImage;
System.out.println("IMAGE SWITCHED!!!! Current Image="+imageList.get(imageIndex));
j.switchImage(currentImage, j.jF, j.jL, j.jP, currentGazeData);
}
}
}
Probably won't fix your problem but you have incorrect Swing coding practices:
jL.setIcon(newIcon);
//jF.add(jL); // remove
jP.add(jL);
jF.add(jP);
jF.validate();
A Swing component can only have a single parent. First you add the label to the frame and the to the panel. So the label will only ever appear on the panel. Get rid of the first statement.
All the Swing components should be added to the frame BEFORE the frame is made valid. So get rid of the validate() statement and move the setVisible(...) to the bottom.
jL.setIcon(newIcon);
//jP.add(jL);
//jF.validate();
When you change a property of a Swing component the component is smart enough to repaint itself. All you need to do is change the icon of the label. There is no need to add the label back to the panel or validate() the frame.
Others dont seem to show up on the screen at all
Maybe the image isn't found?
The drawstring seems to work perfectly.
Instead of creating all the BufferedImages and doing custom painting you can just display a label on top your label.
So the basic code would be:
imageLabel = new JLabel();
imageLabel.setLayout( new FlowLayout() );
textLabel = new JLabel();
imageLabel.add(textLabel);
frame.add(imageLabel);
Note:
The imageLabel can be added directly to the frame. I don't see any reason for your panel.
To change the image you just invoke the setIcon() method on the imageLabel
To change the text your just invoked the setText() method on the textLabel
Related
I'm working on a GUI for a Tic Tac Toe project, in which I want to get an image (the player's move) to show up when clicking the corresponding area. However, I can't figure out how to display a JLabel (the move) on top of another JLabel (the background).
I have searched and tried to use layeredpanes, but it just fails to show the entire frame when I run it. I am new to GUI, so I am not quite sure if I implemented it correctly.
layer = new JLayeredPane();
//set up the board as background
String path = "sampleUrl";
URL url = new URL(path);
BufferedImage image = ImageIO.read(url);
bg4 = new JLabel(new ImageIcon(image));
layer.add(bg4, new Integer(-1));
frame.add(layer);
frame.pack();
frame.addMouseListener(new MouseListener4());
String xPath = "sampleUrl";
URL xUrl = new URL(xPath);
BufferedImage x = ImageIO.read(xUrl);
icon = new JLabel(new ImageIcon(x));
layer.add(icon);
It just shows up a window with minimum width and height, without displaying the background. Is there something wrong with this code, or any other ways for me to put a JLabel on top of another JLabel?
You can add one label object into another, as JLabel is a container. Try something like this.
JLabel parentLabel = new JLabel("Parent");
JLabel childLabel = new JLabel("Child");
parentLabel.add(childLabel );
I highly recommend you to read about javafx if you are new in GUI.you can merge nodes in any way you need.you can put labels on each other using stackpane,and display them top and down of each other using gridpane very easily.
more information on:
https://docs.oracle.com/javafx/2/
I have a JFrame and an ImageIcon as a JLabel that I want to appear fully off of the JFrame.
Code:
JFrame frame = new JFrame("test");
frame.setSize(1000, 1000);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try {
BufferedImage bf = ImageIO.read(new File(FILEPATH));
img = new JLabel(new ImageIcon(bf));
} catch (IOException e) {
e.printStackTrace();
}
frame.getContentPane().add(img);
img.setBorder(new EmptyBorder(0, frame.getContentPane().getWidth(), 0, 0));
This code only makes the JLabel/image appear half off of the screen. I can easily fix it by setting the left parameter of the EmptyBorder to frame.getContentPane.getWidth() * 2, but I am just wondering why it seems to cut the inset distance in half. From my testing, only cuts it in half if the JLabel contains an ImageIcon. If it contains text, the insets work as they seem like they should. I have only tested with text and ImageIcon.
Not sure what the exact calculation is, but by default the Icon is centered in the space available.
As you noticed it appears that when only the Icon is displayed the Icon appears to be moved to the left by half the size of the Icon.
This does not happen if you have both an Icon and text (or just text).
One solution is:
img = new JLabel(new ImageIcon(bf), SwingConstants.LEFT);
I´m writing a program where images are displayed on a JPanel, but I´m having trouble replacing the existing image when I open a new one. Is there a easy way to remove the old image from the ImageIcon and replace with the new one? I thought that something like mp.remove(pic); would work here, but it says that it´s not supported for ImageIcon?
class MapPanel extends JPanel {
public MapPanel(String filename) {
if(mp == null) {
pic = new ImageIcon(filename);
int w = pic.getIconWidth();
int h = pic.getIconHeight();
setPreferredSize(new Dimension(w, h));
setMinimumSize(new Dimension(w, h));
setMaximumSize(new Dimension(w, h));
setLayout(null);
}
else { int confirm =
JOptionPane.showConfirmDialog(MapProgram.this, "Unsaved changes, " +
"do you really want to open a new map?",
"New map", JOptionPane.OK_CANCEL_OPTION);
if (confirm != JOptionPane.OK_OPTION)
return;
// Remove the current image and display the new one choosen
// from the JFileChooser.
}
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(pic.getImage(), 0, 0, this);
}
}
Why are you using ImageIcon at all? It appears you want to draw an Image in a JPanel, not sure why you are using ImageIcon. Use ImageIO.read() to read the file chosen by the file chooser as an BufferedImage. Set the image to a member variable, then in paintComponent() instead of pic.getImage(), use your member variable. After a file is chosen and you set your member variable to the new file call repaint().
https://docs.oracle.com/javase/8/docs/api/javax/imageio/ImageIO.html#read-java.io.File-
Also, setting preferredSize, min size, and max size may or may not do anything. It all depends on what layout manager the container you put this JPanel in is using.
Not sure if this will work for what you want to do but give it a try.
g.drawImage(new ImageIcon(filename).getImage(), 0, 0, this);
or just pass in an Image there.
So, I have a grid layout which stores JScrollPane's in each cell. These are also put into an array for other purposes. The "View" extends "JPanel" so it's just a regular panel with image support. The application starts up with cell's filled with scrollPane's that contain the View which doesn't have a image yet.
At that point I see no scrollbar, but that doesn't matter since there is nothing inside the JPanel. As soon as I open an image and use drawImage in the paintComponenet of the JPanel I don't see scrollbar's showing up. Here's how I create the grid and the Scrollpane
private void createContentPane()
{
GridLayout gridLay = new GridLayout(GRID_ROWS, GRID_COLUMNS);
perspectiveTbl = new JScrollPane[NUM_PERSPECTIVE];
mainPane = new JPanel();
mainPane.setLayout(gridLay);
int idx = 0;
while(idx < perspectiveTbl.length)
{
perspectiveTbl[idx] = new JScrollPane(new View(modelImage));
mainPane.add(perspectiveTbl[idx]);
idx++;
}
this.getContentPane().add(mainPane, BorderLayout.CENTER);
}
I'm not exactly sure why the scrollbar's aren't showing up, should they have been set inside the panel for the image?
Here's an image of the application, as you can see the picture of the shoe does not receive scrollbar's so there is no way to view the rest of the picture:
Picture
You can either user not JPanel with image but usual JLabel with the image
or
call setPreferredSize() for the panels to reflect the image's size.
Thanks for the hint Stanislav, I actually figured it out and got it working an hour ago, but you did give the right path to fix it with the preferredSize attribute. I ended up re-implemented getPreferredSize with the size of the image inside the panel, added revalidate to the paint event so that the bars show up as soon as the image is loaded.
public void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawImage(image, 0, 0, null);
this.getViewScrollPane().revalidate();
}
public Dimension getPreferredSize()
{
if(image != null)
return new Dimension(image.getWidth(),image.getHeight());
else
return super.getPreferredSize();
}
I'm attempting to create my own custom ToolTip for a program I've ported to Java, I'm trying to match the original programs ToolTips (it was written in Delphi). I've got some code that allows me to draw "inside" a ToolTip but for some reason, if I Override paint(Graphics g, JComponent c) and leave it blank it still draws a ToolTip, and anything I attempt to draw will be drawn "inside" this little boxed ToolTip and I can't draw "outside" of it.
import java.awt.*;
import javax.swing.*;
import javax.swing.plaf.basic.BasicToolTipUI;
class MultiLineToolTipUI extends BasicToolTipUI {
#Override
public void paint(Graphics g, JComponent c) {
//int mY = 0;
//int mX = 0;
//int xPoints[] = {mX, mX, mX + 15};
//int yPoints[] = {mY, mY + 25, mY + 25};
//Polygon p = new Polygon(xPoints, yPoints, 3);
//g.setColor(Color.BLACK);
//g.fillPolygon(p);
//g.fillRoundRect(mX, mY, 100, 50, 30, 30);
}
public static void main (String args[])
{
JButton button = new JButton ("Mouse Over ME!") {
public JToolTip createToolTip() {
MultiLineToolTip tip = new MultiLineToolTip();
tip.setComponent(this);
return tip;
}
};
//JButton button = new JButton("Mouse Over ME!");
button.setToolTipText("Hello, World");
JFrame frame = new JFrame("Basic SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( button );
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible( true );
}
static class MultiLineToolTip extends JToolTip
{
public MultiLineToolTip()
{
setUI(new MultiLineToolTipUI());
}
}
}
This is what I have, and like I said, even without the lines in paint it's drawing on it's own.
Any advice to get around this? Or a better way to go about what I'm trying to do?
CLARIFICATION: The first answer by Camickr was very helpful, however I should clarify my goal is to get the box that is automatically drawn from somewhere outside of paint to go away, or be invisible.
The size of the tool tip is determined by the text. Add:
System.out.println( c.getSize() );
to the paint(...) method to see the size of the tool tip. You are trying to paint outside its bounds. If you want to override the default size then you need to set the preferred size yourself. I think you want:
public Dimension getPreferredSize(JComponent c)
{
return new Dimension(100, 50);
}
Edit: A tooltip is a component with a border and a background. If you want to remove them you can use:
tip.setOpaque(false);
tip.setBorder(new javax.swing.border.EmptyBorder(0, 0, 0, 0));
This will only work when to tooltip is fully contained withing the frame. When the tooltip is displayed outside the bounds of the frame, then the tooltip is added to a JWindow, in which case you will see the background of the window. I don't know how to disable this behaviour because all Swing components must be painted within the bounds of a top level container.