Adapting pixels of the image depending files and rows - java

I have this function where I receive String[][], f (rows), and c (columns). I've got to adapt my labels occupying all of my frame (1270,750).
For example, if I receive:
f=3 and c=3, the images will have: (423.333,250.) pixels
f=10 and c=10, the images will have (127,75) pixels.
I've proved with all the functions which are in the example, but it doesn't work. Any idea how to do it?
public void inicialitzamatriu(String[][] arraystrings,int f,int c) {
ff=f;
cc=c;
compsToExperiment=new JPanel();
GridLayout experimentLayout = new GridLayout(ff,cc);
compsToExperiment.setLayout(experimentLayout);
this.setContentPane(compsToExperiment);
for (int filas=0;filas<ff;filas++){
for (int columnas=0;columnas<cc;columnas++){
if (arraystrings[filas][columnas].equals("gat")){
JLabel cat2 = new JLabel();
cat2.resize(1270/cc, 750/cc);
cat2.setIcon(new ImageIcon("cat.png"));
compsToExperiment.add(cat2);
/*cat2.getSize();
//cat2.getWidth();
//cat2.getHeight();
cat2.resize(width, height);
cat2.setBounds(x, y, width, height)
cat2.setSize(width, height)
cat2.
*/
}
if (arraystrings[filas][columnas].equals("rat")){
JLabel rat2 = new JLabel();
rat2.setSize(1270/cc, 750/cc);
rat2.setIcon(new ImageIcon("raton.png"));
compsToExperiment.add(rat2);
}
if (arraystrings[filas][columnas].equals("menjar")){
JLabel comida2 = new JLabel();
comida2.setSize(1270/cc, 750/cc);
comida2.setIcon(new ImageIcon("comida.png"));
compsToExperiment.add(comida2);
}
if (arraystrings[filas][columnas].equals("res")){
JLabel nada2 = new JLabel();
nada2.setSize(1270/cc, 750/cc);
nada2.setIcon(new ImageIcon("nada.png"));
compsToExperiment.add(nada2);
}
}
}
this.repaint();
//compsToExperiment.repaint();
compsToExperiment.setVisible(true);
//this.setVisible(true);
//this.setVisible(false);
}

You need to do custom painting to scale the image to the space available in the grid.
You can try using Darryl's Stretch Icon (or maybe the Shrink Icon).

Related

How to resize images in JScrollPane as frame resizes

I need to develop an image gallery of sorts, where I can display images in a JFrame, and I can scroll and double click to expand to full screen etc. I was able to display the images the way I want it, but when I resize the JFrame, the images gets cut off as there is no horizontal scroll.
Is there a way where I can have have vertical scroll and when frame resizes, the panel within will resize to fit horizontally?
try {
BufferedImage readImage = ImageIO.read(new File("myFile.png"));
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(readImage, "png", bos);
byte[] data = bos.toByteArray();
BufferedImage image = ImageIO.read(bis);
JPanel imagePanel = new JPanel();
imagePanel.setLayout(new GridLayout(0,2,5,5));
for (int x=0;x<8;++x){
JLabel l = new JLabel(new ImageIcon(image));
imagePanel.add(l);
}
JScrollPane scrollPane = new JScrollPane(mainPanel, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
JFrame frame = new JFrame();
frame.add(scrollPane);
//frame.add(imagePanel); //This will work as i intended it to be, but there is no vertical scroll
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
} catch (IOException e) {
e.printStackTrace();
}
Edit:
A visual example is shown below. When the frame resizes, the images get cropped, what I would like instead are for the images within the JScrollPane to resize so that it could all fit horizontally, while at the same time maintaining the vertical scroll.
Edit2:
Using StretchIcon, I was able to achieve having the images resize dynamically, but this introduced another issue where there are huge spaces in between the images as I resize.

Using JLabel to flip through images

I'm trying to flip through multiple images using previous and next button.
Currently, the layout is:
and this is my code:
public void createWalkthrough() {
if(currentframe != null) {
currentframe.setVisible(true);
return;
}
currentframe = new JFrame("Getting Started");
JPanel imagePanel = new JPanel();
imagePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
imageArea = new JLabel();
imagePanel.add(imageArea);
JButton previousButton = new JButton("Previous");
previousButton.addActionListener(this);
previousButton.setActionCommand("Previous");
JButton nextButton = new JButton("Next");
nextButton.addActionListener(this);
nextButton.setActionCommand("Next");
JPanel panelButtons = new JPanel();
panelButtons.setLayout(new BoxLayout(panelButtons, BoxLayout.LINE_AXIS));
panelButtons.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
panelButtons.add(Box.createRigidArea(new Dimension(10, 0)));
panelButtons.add(Box.createHorizontalGlue());
panelButtons.add(previousButton);
panelButtons.add(nextButton);
currentframe.setSize(439, 548);
currentframe.setResizable(false);
Container pane = currentframe.getContentPane();
pane.add(imagePanel, BorderLayout.CENTER);
currentframe.add(panelButtons, BorderLayout.PAGE_END);
currentframe.setVisible(true);
currentframe.requestFocusInWindow();
}
public void displayImage(int index) {
File[] imagesList = getImages();
File imageName = imagesList[index];
ImageIcon icon = new ImageIcon(imageName.getAbsolutePath());
Image image = icon.getImage().getScaledInstance(imageArea.getWidth(), imageArea.getHeight(), Image.SCALE_SMOOTH);
imageArea.setIcon(new ImageIcon(image));
}
public File[] getImages() {
File folder = new File("/Users/jwh/Desktop/img");
File[] listofImages = folder.listFiles();
return listofImages;
}
#Override
public void actionPerformed(ActionEvent e) {
if(base == null) {
return;
}
String selected = e.getActionCommand();
if(selected.equals("Previous")) {
pos = pos - 1;
if(pos < 0) {
pos = 0;
}
displayImage(pos);
} else if(selected.equals("Next")) {
pos = pos + 1;
if(pos >= getImages().length) {
pos = getImages().length;
}
displayImage(pos);
}
}
I'm not sure what I am doing wrong. I feel like I keep going around in circles by trying different things on different StackOverflow posts.
The error that I am currently getting is:
"Exception in thread "AWT-EventQueue-0" java.lang.IllegalArgumentException:
Width (0) and height (0) must be non-zero"
Any help would be greatly appreciated. Thank you!!
Your primary problem comes down to the compounding nature of your layouts and misunderstanding of the default layouts...
JPanel imagePanel = new JPanel();
imagePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
imageArea = new JLabel();
imagePanel.add(imageArea);
imagePanel, by default, is using a FlowLayout, which will attempt to honour the preferredSize of the components added to it.
JLabel, by default, has a preferredSize of 0x0.
So, when you do something like...
Image image = icon.getImage().getScaledInstance(imageArea.getWidth(), imageArea.getHeight(), Image.SCALE_SMOOTH);
you're actually passing 0x0 to the getScaledInstance method.
While there are number of ways to fix it, the simplest would be to use a layout manager which wants to fill the available space, like BorderLayout...
JPanel imagePanel = new JPanel(new BorderLayout());
imagePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
imageArea = new JLabel();
imagePanel.add(imageArea);
Feedback...
Okay, a number of small issues...
getScaledInstance does not produce the best result, nor is the fastest way to scale an image. Now, if you'd prefer not to use a library, like imgscalr, you could use something like Java: maintaining aspect ratio of JPanel background image and Quality of Image after resize very low -- Java to scale the images
It's some what of a personal thing, but I don't like the ImageIcon API, it doesn't provide feedback about why an image might not have been loaded and doesn't support a large range of image formats.
Personally, I prefer to use the ImageIO API instead. See Reading/Loading an Image

JLabel + images

I'm applying an image to a JLabel using the command .setIcon() and then adding the label to a panel
public browser() throws IOException {
JLabel lblimg;
Image img;
ImageIcon ico;
img = ImageIO.read(new File("<FilePath>"));
ico = new ImageIcon(img);
lblimg.setIcon(ico);
lblimg.setBounds(300,90,120,120);
add(lblimg);
}
but this doesn't resize the image inside the label, this way just a slice of the image will appear if it is bigger than the label size.
Does anyone knows a method to insert an image to a label background, resizing the image into it?
Create a BufferedImage and get scaled instance, set its width and height to the width and height to that of the label. Now if you even resize the label, the image will cover the label.
For Example: lblimg.setBounds(300, 90, 300, 120);
BufferedImage bimg =ImageIO.read(new File("file path"));
ico = new ImageIcon(bimg.getScaledInstance(lblimg.getWidth(), lblimg.getHeight(), Image.SCALE_SMOOTH));
lblimg.setIcon(ico);
The following image has been scaled according to the label's width and height.
lblimg.setBounds(300, 90, 100, 50);
Here's a method I wrote some years back to resize an image in Java.
public ImageIcon picturePrep(ImageIcon icon) {
final int DESIRED_WIDTH = 880;
double imageWidth = icon.getIconWidth();
int imageHeight = icon.getIconHeight();
imageWidth = DESIRED_WIDTH/imageWidth;
imageHeight = (int) (imageWidth * imageHeight);
Image img = icon.getImage();
return new ImageIcon(img.getScaledInstance(DESIRED_WIDTH, imageHeight, Image.SCALE_SMOOTH));
}
Use a appropriate layout manager to take care it for you automatically. See Laying Out Components Within a Container for more details.
If, for some bizarre reason, you can't use a layout manager, then you should probably be considering a solution based around custom painting, you could make use of the components preferred size to provide it better information when settings it's bounds
BufferedImage img = ImageIO.read(new File("<FilePath>"));
JLabel lblimg = new JLabel(new ImageIcon(img));
lblimg.setBounds(new Rectangle(new Point(300, 90), lblimg.getPreferredSize()));
Then, you don't need to make guesses

How to draw the subtitle that is in the ImageJ window

I have made my own customized GUI where it displays images that are opened and read by ImageJ. I am able to display the images but I can't display the subtitle that is displayed in the ImageJ window before the image.
This is what I have been trying but it doesn't seem to display anything. Is there something simple that I am missing?
JPanel panel2 = new JPanel();
ImageCanvas ic = new ImageCanvas(image);
StackWindow sw = new StackWindow(image,ic);
Insets insets = sw.getInsets();
BufferedImage bi = image.getBufferedImage();
Graphics2D g = (Graphics2D)bi.getGraphics();
//g.drawImage(image.getBufferedImage(), 0, 0, null);
g.drawString(sw.createSubtitle(), insets.left+5, insets.top+10);
//image.draw();
sw.drawInfo(g);
panel2.add(sw.getContentPane());
frame.add(panel2);

Java fixed element's position

I need to build BlackJack game as an study project.
I want build it with SWING GUI. What I need it just divide the screen in 2 parts, and then to be able insert elements (in my case it's extended JButton with signed ImageIcon) using absolute (x, y) position relative to specified part.
Something like that:
I came from developing under Android, where you can work with elements in very simple way, and I feel lost in SWING. There aren't AbsoluteLayout or something like that?
Here is one example of my several attempts to this:
public void run() {
// TODO Auto-generated method stub
JFrame jFrame = new JFrame("Blackjack");
jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Container pane = jFrame.getContentPane();
Insets insets = pane.getInsets();
URL url = ClassLoader.getSystemClassLoader().getResource("10_of_clubs.png");
BufferedImage bi = null;
try {
bi = ImageIO.read(url);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Image resizedImage = bi.getScaledInstance(128, 186, 0);
ImageIcon icon = new ImageIcon(resizedImage);
ImageButton imgButton = new ImageButton(icon);
imgButton.setPreferredSize(new Dimension(128, 186));
ImageButton imgButton2 = new ImageButton(icon);
imgButton.setPreferredSize(new Dimension(128, 186));
pane.setLayout(new GridBagLayout());
JPanel headPanel = new JPanel();
JPanel headPanel2 = new JPanel();
GridBagConstraints cns = new GridBagConstraints();
cns.gridx = 0;
cns.gridy = 0;
cns.weightx = 0.5;
cns.weighty = 0.2;
cns.anchor = GridBagConstraints.FIRST_LINE_START;
cns.fill = GridBagConstraints.BOTH;
headPanel.setBackground(Color.RED);
headPanel.add(imgButton, cns);
GridBagConstraints cns2 = new GridBagConstraints();
cns2.gridx = 0;
cns2.gridy = 0;
cns2.weightx = 0.5;
cns2.weighty = 0.2;
cns2.anchor = GridBagConstraints.FIRST_LINE_START;
cns2.fill = GridBagConstraints.CENTER;
headPanel2.setBackground(Color.BLUE);
headPanel2.add(imgButton2, cns2);
pane.add(headPanel);
pane.add(headPanel2);
jFrame.setSize(800, 600);
jFrame.setVisible(true);
jFrame.setLocationRelativeTo(null);
}
That what I get:
Tnx.
if you want absolute layout, please take a look at: http://docs.oracle.com/javase/tutorial/uiswing/layout/none.html
in general to read about layouts in java you can take a look at:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
here is all java swing components: visual guide:
http://docs.oracle.com/javase/tutorial/uiswing/layout/visual.html
I think you can use JSplitPane (http://algo.math.ntua.gr/~symvonis/other-material/java_material/JavaTutorial/uiswing/components/splitpane.html) to create vertical separation
Since you have overlapping elements you can:
Use your existing JButtons with images inside a JLayeredPane. Put your cards on different layers for a clean rendering. Set the position of your Cards absolute with 'setBounds()'
Draw your cards with absolute position yourself using a Canvas. If you take this approach, you will also have to do your Click handling yourself (check if a click is inside a card.)

Categories

Resources