I have made a Board class, where I import an image using ImageIcon and, instead of making a picture with the specified resolution, I want it to be full screen for any type of monitor.
public Board() {
p = new Dude();
addKeyListener(new AL());
setFocusable(true);
ImageIcon i = new ImageIcon("C:/test.jpg");
img = i.getImage();
time = new Timer(5, this);
time.start();
}
I've used this code before:
public class MainMenu2 {
MainMenu2() throws IOException{
JFrame Main_Menu = new JFrame("Main Menu");
Main_Menu.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
final int widthScreen = screenSize.width;
final int heightScreen = screenSize.height;
BufferedImage backgroundImage = ImageIO.read(new File("P://My Pictures//background1.jpg"));
JLabel background = new JLabel(new ImageIcon(backgroundImage));
Image scaleBackground = backgroundImage.getScaledInstance(widthScreen, heightScreen, Image.SCALE_SMOOTH);
ImageIcon imageIcon = new ImageIcon(scaleBackground);
Main_Menu.setContentPane(new JLabel(imageIcon));
which uses scale smooth, which sets the image to the screen width and height, but I don't know how to apply it to my current code. The difference between both is that, Board class extends JPanel, and MainMenu2 is just a normal class, where a JFrame is created, etc. Please help! Thank you.
At the most basic level, it might look some like this...
ImageIcon i = ImageIO.read(new File("C:/test.jpg"));
Image scaleBackground = backgroundImage.getScaledInstance(widthScreen, heightScreen, Image.SCALE_SMOOTH);
img = scaleBackground.getImage();
Now, problems - the size of the component isn't likely to match he size of the screen.
As a preference, I might be tempted to do something like Scale the ImageIcon automatically to label size
You should also read The Perils of Image.getScaledInstance()
Related
I have used every popular way to display picture in java swing, but with every method the picture losses quality even without any kind of resizing. No matter what format GIF, PNG, JPEG the picture doesn't appear like the original one outside of the code. I have tested swing code to display images on other computers, it works fine on them but not on my computer.
These are the methods I have tried so far:
Note- To keep the things short the code below is for example only.
1.Graphics method
public class mainClass extends Canvas {
public void paint(Graphics g){
Toolkit t = Toolkit.getDefaultToolkit();
Image i = t.getImage(getClass().getResource("monsters.png"));
g.drawImage(i, 0 , 0, this);
}
public static void main(String []args){
mainClass m = new mainClass();
JFrame frame = new JFrame();
frame.add(m);
frame.setSize(800,800);
frame.setVisible(true);
frame.setLocationRelativeTo(null);
}
}
Simple JLabel setIcon method
ImageIcon gif = new ImageIcon("Loading2 (1).gif");
label.setIcon("gif");
Scaled JLabel setIcon method
public ImageIcon create(ImageIcon i ,int x,int y){
Image img = i.getImage();
Image imgScaled = img.getScaledInstance(x,y,Image.SCALE_SMOOTH);
return new ImageIcon(imgScaled);
}
Comparison:
Original
JavaOutput
I'm trying to make a game of chess, but when I try to insert chess pieces through JLabel icons, they cover the actual chessboard, thus only having the pieces left on screen. How do I make the JLabels not cover up paintings behind it? I'm doing this using a class that extends JApplet.
UPDATE: it worked by using Applet instead of JApplet, though I still have no idea why.
This is the code:
ChessBoard board; // done in another class file
public static int CEL_WIDTH = 65;
public static int MARGIN_X = 50, MARGIN_Y = 50;
imagePos = "../src/Schack/Bilder/";
JLabel label;
public void init() {
setLayout(null);
this.setSize(600, 600);
board = new ChessBoard(MARGIN_X, MARGIN_Y, CEL_WIDTH);
ImageIcon imageIcon = new ImageIcon(getImage(getDocumentBase(), imagePos + "blackRook.png")); //scaling my image
Image image = imageIcon.getImage();
Image newimg = image.getScaledInstance(CEL_WIDTH, CEL_WIDTH, java.awt.Image.SCALE_SMOOTH);
imageIcon = new ImageIcon(newimg);
label = new JLabel(imageIcon);
label.setBounds(MARGIN_X, MARGIN_Y, CEL_WIDTH, CEL_WIDTH);
add(label);
}
#Override
public void paint(Graphics g) {
board.paintChessBoard(g); // another paint method in a different class file
super.paint(g);
}
I have png icons and use them as icons in JButton / JLabel.
The problem is that the image displayed at runtime is larger than the original icon, and because of this resizing, it's super ugly.
Here is an example:
Original icon (left) and how it's rendered in the JButton (right)
The source code for this minimal example is simply:
public class Main {
public static void main(String... args) {
JFrame frame = new JFrame("Test");
frame.setBounds(0, 0, 120, 80);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new FlowLayout());
ImageIcon icon = new ImageIcon("icon.png");
frame.getContentPane().add(new JButton("Test", icon));
frame.setVisible(true);
}
}
Is this expected? If not, how can I avoid this? I tried many things around forcing the size of the image, the button, etc. but could not get a proper image displayed.
I have tested with icons of various sizes: 16x16, 17x17, 18x18, 19x19, 20x20, and each time the icon displayed on the JButton is a bit larger than the original which makes it look ugly:
Thank you!
Cheers.
This is because you are using Windows scaling. The entire component is scaled, both the icon and the text.
You could turn the scaling of the Icon off by using a wrapper Icon:
import java.awt.*;
import java.awt.geom.AffineTransform;
import javax.swing.*;
public class NoScalingIcon implements Icon
{
private Icon icon;
public NoScalingIcon(Icon icon)
{
this.icon = icon;
}
public int getIconWidth()
{
return icon.getIconWidth();
}
public int getIconHeight()
{
return icon.getIconHeight();
}
public void paintIcon(Component c, Graphics g, int x, int y)
{
Graphics2D g2d = (Graphics2D)g.create();
AffineTransform at = g2d.getTransform();
int scaleX = (int)(x * at.getScaleX());
int scaleY = (int)(y * at.getScaleY());
int offsetX = (int)(icon.getIconWidth() * (at.getScaleX() - 1) / 2);
int offsetY = (int)(icon.getIconHeight() * (at.getScaleY() - 1) / 2);
int locationX = scaleX + offsetX;
int locationY = scaleY + offsetY;
AffineTransform scaled = AffineTransform.getScaleInstance(1.0 / at.getScaleX(), 1.0 / at.getScaleY());
at.concatenate( scaled );
g2d.setTransform( at );
icon.paintIcon(c, g2d, locationX, locationY);
g2d.dispose();
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
public static void createAndShowGUI()
{
JButton button = new JButton( "Button" );
NoScalingIcon icon = new NoScalingIcon( new ImageIcon("box.jpg") );
button.setIcon( icon );
JPanel panel = new JPanel( );
panel.add( button );
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(panel);
f.setSize(200, 200);
f.setLocationRelativeTo( null );
f.setVisible(true);
}
}
The scaling adjustment will position the Icon at the top/left of the button area.
The offset adjustment will then attempt to center the Icon in the scaled icon painting area.
Using the default transform will have a scaling factor of 0 for the Icon.
Thank you all.
The problem was the default scaling factor (which was 1.25).
As I want to be fully in control of the size independently from DPI, I solved my issue by forcing the scaling factor to 1.0.
This answer was helpful
So, either pass to the command line
-Dsun.java2d.uiScale=1.0,
or set it programmatically
System.setProperty("sun.java2d.uiScale", "1.0")
Look at the source code for the constructor of class ImageIcon that takes a string parameter. It uses class java.awt.Toolkit to create the image from the file. This made me think that it must be doing some scaling. So I thought of creating the icon differently. ImageIcon has another constructor that takes an Image parameter. So I created a BufferedImage from the file and then used that image to create an ImageIcon. The BufferedImage is not scaled.
Note that your link to the icon file didn't work for me so I just downloaded a different 16x16 icon.
java.awt.image.BufferedImage img = javax.imageio.ImageIO.read(new java.io.File("cellphon.png"));
javax.swing.Icon ico = new javax.swing.ImageIcon(img);
javax.swing.JButton button = new javax.swing.JButton("Test", ico);
I'm writing a little photo application (asked some questions before) and I have one problem which I cannot resolve. The idea is that there are two sections: the upper one is for an overview (using thumbnails) and the lower one shows the selected image in it's full size. I cannot use ImageIO (required by my lecturer).
I'm using a JList for the overview but most images are not visible. I chose a folder with about 20 images and only 2 show up. And one of them isn't even centered.
For some reason, if I delete those lines:
thumbnaillist.setFixedCellWidth(thumbW);
thumbnaillist.setFixedCellHeight(thumbH);
One image shows up that wasn't visible before, but now the other two disappear.
This is my code:
public class PVE extends JFrame {
private JFileChooser fileChoose;
//MenuBar
private JMenuBar menubar;
private JMenu file;
private JMenuItem openFolder;
private JMenuItem exit;
//Thumbnails
private JList thumbnaillist;
private DefaultListModel<ImageIcon> listmodel;
private JScrollPane tscroll;
private ImageIcon thumbs;
private int thumbW = 100;
private int thumbH = 100;
//for full size view
private JPanel imgview;
public PVE() {
setLayout(new BorderLayout());
//MenuBar
menubar = new JMenuBar();
file = new JMenu("File");
openFolder = new JMenuItem("Open folder...");
exit = new JMenuItem("Quit");
file.add(openFolder);
file.addSeparator();
file.add(exit);
menubar.add(file);
setJMenuBar(menubar);
fileChoose = new JFileChooser();
openFolder.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
fileChoose.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
fileChoose.showOpenDialog(null);
File chosenDir = fileChoose.getSelectedFile();
loadToThumbView(chosenDir);
}
});
//Thumbnail view
listmodel = new DefaultListModel();
thumbnaillist = new JList(listmodel);
thumbnaillist.setLayoutOrientation(JList.HORIZONTAL_WRAP);
thumbnaillist.setFixedCellWidth(thumbW);
thumbnaillist.setFixedCellHeight(thumbH);
thumbnaillist.setVisibleRowCount(1);
tscroll = new JScrollPane(thumbnaillist, JScrollPane.VERTICAL_SCROLLBAR_NEVER,
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
tscroll.setPreferredSize(new Dimension(0, 100));
add(tscroll, "North");
//for full size view
imgview = new JPanel();
imgview.setBackground(Color.decode("#f7f7f7"));
add(imgview, "Center");
setTitle("Photo Viewer");
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
SwingUtilities.updateComponentTreeUI(this);
} catch (Exception e) {
}
setSize(700, 700);
setLocation(200, 200);
setVisible(true);
}
public void loadToThumbView(File folder) {
listmodel.removeAllElements();
File[] imgpaths = folder.listFiles();
for (int j = 0; j < imgpaths.length; j++) {
listmodel.addElement(resizeToThumbnail(new ImageIcon(imgpaths[j].toString())));
}
}
public ImageIcon resizeToThumbnail(ImageIcon icon) {
Image img = icon.getImage();
BufferedImage bf = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
Graphics g = bf.createGraphics();
g.drawImage(img, 0, 0, thumbW, thumbH, null);
ImageIcon kB = new ImageIcon(bf);
return kB;
}
public static void main(String argv[]) {
PVE pv = new PVE();
}
}
Your problem is because of the way you're scaling your images.
I'm not exactly sure why but I guess it has something to do with the BufferedImage#createGraphics() call and that I was able to reproduce the problem with .jpg images while .png files were correctly painted.
However if you scale your images instead of converting them to a BufferedImage and getting a new ImageIcon from it, you get the correct output:
public ImageIcon resizeToThumbnail(ImageIcon icon) {
Image img = icon.getImage();
Image scaled = img.getScaledInstance(thumbW, thumbH, Image.SCALE_SMOOTH);
return new ImageIcon(scaled);
}
This is the folder I used to test:
And the outputs with your code and mine:
Important notes
And as as a recommendation don't make a window that big if all you're using is that little bar above. If you're adding something else below, then it's ok but for now it's not that "user friendly" (IMHO). Instead of JFrame#setSize() you could try using JFrame#pack() method so your frame resizes to it's preferred size.
Some other things I noted in your program:
You're not placing it inside the Event Dispatch Thread (EDT) which is dangerous since your application won't be Thread safe that way. You can change that if you change your main method as follows:
public static void main(String argS[]) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
PVE pv = new PVE();
}
});
}
You're setting the JScrollPane preferred size, instead you should override its getPreferredSize() method, see Should I avoid the use of setPreferred|Maximum|MinimumSize methods in Java Swing? (YES)
You're extending JFrame, you should instead create an instance of it unless you're overriding one of its methods (and you're not, so don't do it) or you have any good reason to do it. If you need to extend a Container you should extend JPanel instead, as JFrame is a rigid container which cannot be placed inside another one. See this question and this one.
I think I'm not missing anything, and hope this helps
Your “scaled” images are actually images which are the same size as the original image, but are blank except for a scaled version drawn in the upper left corner. That upper left corner is clipped out of view in each rendered cell (at least for the somewhat large images I tested with).
The scaled image needs to be created with the thumbnail size, not the size of the original image. Meaning, change this:
BufferedImage bf = new BufferedImage(img.getWidth(null), img.getHeight(null), BufferedImage.TYPE_INT_ARGB);
to this:
BufferedImage bf = new BufferedImage(thumbW, thumbH, BufferedImage.TYPE_INT_ARGB);
How to display an image to JPanel or to JLabel using the BufferedImage?
I load an Image using FileChooser and I need to display what I've loaded.
I don't extend my class to any container.
Override paintComponents(g) paintComponent(g) method of JPanel or JLabel and draw image in it. Something like follow:
JPanel panel = new JPanel(){
#Override
public void paintComponent(Graphics g) {
BufferedImage image = null; // get your buffered image.
Graphics2D graphics2d = (Graphics2D) g;
graphics2d.drawImage(image, 0, 0, null);
super.paintComponents(g);
}
};
Same thing for JLabel. Or in another way:
BufferedImage image = null; // get your buffered image.
ImageIcon icon = new ImageIcon((Image)image);
JLabel label = new JLabel();
label.setIcon(icon);
As you are saying that you are loading image from FileChooser it can be done in following
way:
ImageIcon icon = new ImageIcon(
fileChooser.getCurrentDirectory().toString()
+"/"+fileChooser.getSelectedFile().getName());
Now you can use ImageIcon in JLabel or add it in JPanel.
Above code is sample code and not tested so not necessary to run without error. You might need to change it as per your need.