1

I am actually trying to make a simple image viewer using Java. It includes a label and three buttons. Two of these buttons act as left and right arrow keys for navigation and 3rd is an open button to select a directory. However, when I click on open only the first JPG image is viewed and that too unscaled . If I click on the forward button, the navigation does not happen.

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.tree.*;
import java.io.*;


public class picframe extends Thread implements ActionListener
{
  JTree tr;
  JScrollPane jsp;
  JFrame f;
  JButton b1,b2,b3;
  JLabel lab;
  File fl;
  File[] flist;
  ImageIcon ig;
  int k,j=0;
  FileDialog fdial;
  String str;

  picframe()
  {
    f=new JFrame("My Frame");
    f.setVisible(true);
    f.setLayout(null);


    lab=new JLabel();
    lab.setBounds(100,50,1166,500);
    f.add(lab);

    b1=new JButton(" <| ");
    b1.setBounds(486,600,100,30);
    b1.setEnabled(false);
    f.add(b1);
    b1.addActionListener(this);



    b2=new JButton(" |> ");
    b2.setBounds(786,600,100,30);
    f.add(b2);
    b2.setEnabled(false);
    b2.addActionListener(this);

    b3=new JButton("Open");
    b3.setBounds(633,650,100,30);
    f.add(b3);
    b3.addActionListener(this);

    f.pack();
    f.setSize(1366,768);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }

  public void actionPerformed(ActionEvent ae)
  {

    if(ae.getActionCommand().equals("Open"))
    {
      FileDialog fdial=new FileDialog(f,"Open Box",FileDialog.LOAD);
      fdial.setSize(300,300);
      fdial.setVisible(true);
      str=fdial.getDirectory();
      fl=new File(str);
      flist=fl.listFiles();
      b2.setEnabled(true);


      rat:while(j<flist.length)
      {
        if(flist[j].isFile())
        {
          if(flist[j].getName().toLowerCase().endsWith(".jpg"))
          {
            ig=new ImageIcon(fdial.getDirectory()+flist[j].getName());
            lab.setIcon(ig);
            break rat;

          }
        }

        j++;
      }


    }

    if(ae.getActionCommand().equals("<|"))
    {
      --j;

      if(j+1!=0)
      {
        bat:while(j<flist.length)
        {
          if(flist[j].isFile())
          {
            if(flist[j].getName().toLowerCase().endsWith(".jpg"))
            {
              ig=new ImageIcon(fdial.getDirectory()+flist[j].getName());
              lab.setIcon(ig);
              b1.setEnabled(true);
              break bat;
            }
          }

          j--;
        }
      }

      if(j<0 || !flist[j].isFile())
      {
        lab.setText("no image");
      }

      if(ae.getActionCommand().equals("|>"))
      {
        ++j;

        if(j-1!=flist.length)
        {
          cat:while(j<flist.length)
          {
            if(flist[j].isFile())
            {
              if(flist[j].getName().toLowerCase().endsWith(".jpg"))
              {
                ig=new ImageIcon(fdial.getDirectory()+flist[j].getName());
                lab.setIcon(ig);
                b1.setEnabled(true);
                break cat;

              }
            }

            j++;
          }
        }

        if(j>flist.length || !flist[j].isFile())
        {
          lab.setText("no image");
        }
      }

    }
  }
  public static void main(String args[])
  {
    new picframe();
  }


}
Roman C
  • 49,761
  • 33
  • 66
  • 176
  • Use a consistent and logical indent for code blocks. The indentation of the code is intended to help people understand the program flow. – Andrew Thompson Jan 13 '13 at 05:16

2 Answers2

2

and that too unscaled

And what makes you think it should be otherwise?? Swing doesn't provide any components (of the top of my head) that do automatically scale its contents, this, you're going to have to work out for your self. Take a look at these previous questions on the subject for some solutions

Updated #1

You other problems is this f.setLayout(null);, doing this means you suddenly become responsible for managing the size of components, so when you load a new image, it's size may be different from the previous, but you don't seem to make any attempt to update the image label...

Update #2

flist[j].getPath() will give you a better result then fdial.getDirectory()+flist[j].getName() as you may be missing the path separator ;)

Update #3

Here's a working example...without scaling

enter image description here

public class BetterBrowser {

    public static void main(String[] args) {
        new BetterBrowser();
    }

    public BetterBrowser() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new BrowserPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }

        });
    }

    public class BrowserPane extends JPanel {

        private FileModel fileModel;
        private JButton open;
        private JButton next;
        private JButton prev;

        private JLabel image;

        public BrowserPane() {
            fileModel = new FileModel();
            setLayout(new BorderLayout());

            JToolBar tb = new JToolBar();
            tb.add((open = new JButton(new OpenAction(fileModel))));

            add(tb, BorderLayout.NORTH);

            JPanel navPane = new JPanel(new FlowLayout(FlowLayout.CENTER));
            navPane.add((prev = new JButton(new PrevAction(fileModel))));
            navPane.add((next = new JButton(new NextAction(fileModel))));

            add(navPane, BorderLayout.SOUTH);
            add(new JScrollPane((image = new JLabel())));

            fileModel.addListDataListener(new ListDataListener() {
                @Override
                public void intervalAdded(ListDataEvent e) {
                }

                @Override
                public void intervalRemoved(ListDataEvent e) {
                }

                @Override
                public void contentsChanged(ListDataEvent e) {
                    if (e.getIndex0() == -1 && e.getIndex1() == -1) {
                        File file = (File) fileModel.getSelectedItem();
                        try {
                            ImageIcon icon = new ImageIcon(ImageIO.read(file));
                            image.setIcon(icon);
                        } catch (IOException exp) {
                            exp.printStackTrace();;
                            image.setIcon(null);
                        }
                    }
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

    }

    public class OpenAction extends AbstractAction {

        private FileModel model;

        public OpenAction(FileModel model) {
            this.model = model;
            putValue(NAME, "Open");
        }

        public FileModel getModel() {
            return model;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            JFileChooser fc = new JFileChooser();
            fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
            fc.setMultiSelectionEnabled(false);
            switch (fc.showOpenDialog((Component) e.getSource())) {
                case JFileChooser.APPROVE_OPTION:
                    File folder = fc.getSelectedFile();
                    File[] files = folder.listFiles(new FileFilter() {
                        @Override
                        public boolean accept(File pathname) {
                            String name = pathname.getName().toLowerCase();
                            return name.endsWith(".jpg")
                                            || name.endsWith(".png")
                                            || name.endsWith(".gif");
                        }

                    });

                    model.removeAllElements();

                    FileModel model = getModel();
                    for (File file : files) {
                        model.addElement(file);
                    }

                    if (model.getSize() > 0) {
                        model.setSelectedItem(model.getElementAt(0));
                    }
                    break;
            }
        }

    }

    public class FileModel extends DefaultComboBoxModel<File> {
    }

    public abstract class AbstractNavigationAction extends AbstractAction {

        private FileModel fileModel;
        private int direction;

        public AbstractNavigationAction(FileModel fileModel, int direction) {
            this.fileModel = fileModel;
            this.direction = direction;
            fileModel.addListDataListener(new ListDataListener() {
                @Override
                public void intervalAdded(ListDataEvent e) {
                    updateState();
                }

                @Override
                public void intervalRemoved(ListDataEvent e) {
                    updateState();
                }

                @Override
                public void contentsChanged(ListDataEvent e) {
                    updateState();
                }

            });
            updateState();
        }

        protected void updateState() {
            setEnabled(getFileModel().getSize() > 0);
        }

        public FileModel getFileModel() {
            return fileModel;
        }

        public int getDirection() {
            return direction;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            FileModel model = getFileModel();
            if (model.getSize() > 0) {
                File file = (File) model.getSelectedItem();
                int index = model.getIndexOf(file);

                index += direction;
                if (index < 0) {
                    index = model.getSize() - 1;
                } else if (index >= model.getSize()) {
                    index = 0;
                }
                file = model.getElementAt(index);
                model.setSelectedItem(file);
            }
        }

    }

    public class PrevAction extends AbstractNavigationAction {

        public PrevAction(FileModel fileModel) {
            super(fileModel, -1);
            putValue(NAME, "< Previous");
        }

    }

    public class NextAction extends AbstractNavigationAction {

        public NextAction(FileModel fileModel) {
            super(fileModel, 1);
            putValue(NAME, "Next >");
        }

    }

}
Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • without fdial.getDirectory(), the image isn't displayed.. u cn check it out if u want to ! – Udit Raizada Jan 12 '13 at 20:51
  • Sorry, you are right, but you could simply use `flist[j]` which is contains the path and name of the file your interested in. – MadProgrammer Jan 12 '13 at 21:27
  • I updated the "Update 2" section for a better solution to the same problem - IMHO – MadProgrammer Jan 12 '13 at 22:15
  • This good and complete example is probably an answer to some other question not sure it's suitable for the OP is asked. – Roman C Jan 12 '13 at 22:54
  • @romanc Yeah, I got to a point with trying to decipher what the OP was trying to do and decided to demonstrate a possible solution to the over all problem. My main point was to demonstrate the use of the layout manager above other things ;) didn't have time to implement scaling itself. We could argue that trying to fix something that is fundamentally broken is bad practice, but we could also argue teaching people to fish as well (which is why I like your answer) – MadProgrammer Jan 13 '13 at 02:07
  • @MadProgrammer Now, I see your points, I suspected it once the sample code has been posted. But I think you didn't get my point, and it may be something opposite, I don't know if ppl like to consider opposite opinions or continue discuss with it, doesn't matter. And it about refactoring of exited code to fix errors, flow, optimization, improve architecture if possible, apply patterns, etc. I don't think demonstrating anyone's approaches will help someone to improve their skills. And the question hash is an evidence that needs to proof. Other deviations is not appreciated... – Roman C Jan 13 '13 at 12:47
  • @MadProgrammer I didn't even trying to teach you what a bad practice or what a good practice, if you want to answer the question keep yourself with circumstances and bounds according to it. Teaching ppl required skills, I don't have such skills and more I even didn't tried to acquire em ever. So, forget it. Thanks for pointing me out with limitations in my answer. – Roman C Jan 13 '13 at 12:56
1

Mistakes are many mistakes I will help you to fix that mistakes.

First of all FileDialog fdial; sould be placed on the class attr. later reference it, but don't create a local variable.

Now the problem is in the actionPerformed method. First the equals method didn't worked because strings returned by the getActionCommand not correspond.

In the method actionPerformed you should switch between different cases and exit and nothing more.

The j variable used to keep current file in the list of files. Increase and decrease it should no exceed the bounds of the array or ArrayIndexOfBoundException.

The fixed code is:

public class picframe extends Thread implements ActionListener
{
  JTree tr;
  JScrollPane jsp;
  JFrame f;
  JButton b1,b2,b3;
  JLabel lab;
  File fl;
  File[] flist;
  ImageIcon ig;
  int k,j=0;
  FileDialog fdial;

  picframe ()
  {
    f=new JFrame("My Frame");
    f.setVisible(true);
    f.setLayout(null);


    lab=new JLabel();
    lab.setBounds(100,50,1166,500);
    f.add(lab);

    b1=new JButton(" <| ");
    b1.setBounds(486,600,100,30);
    b1.setEnabled(false);
    f.add(b1);
    b1.addActionListener(this);



    b2=new JButton(" |> ");
    b2.setBounds(786,600,100,30);
    f.add(b2);
    b2.setEnabled(false);
    b2.addActionListener(this);

    b3=new JButton("Open");
    b3.setBounds(633,650,100,30);
    f.add(b3);
    b3.addActionListener(this);

    f.pack();
    f.setSize(1366,768);
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  }

  public void actionPerformed(ActionEvent ae)
  {

    if(ae.getActionCommand().equals("Open"))
    {
      fdial=new FileDialog(f,"Open Box",FileDialog.LOAD);
      fdial.setSize(300,300);
      fdial.setVisible(true);
      String str=fdial.getDirectory();
      fl=new File(str);
      flist=fl.listFiles();
      b2.setEnabled(true);
      j = 0;
      if (flist != null)
        while(j<flist.length)
        {
          if(flist[j].isFile())
          {
            if(flist[j].getName().toLowerCase().endsWith(".jpg"))
            {
              ig=new ImageIcon(fdial.getDirectory()+flist[j].getName());
              lab.setIcon(ig);
              break;

            }
          }

          j++;
        }


    }

    if(ae.getActionCommand().equals(" <| "))
    {
      --j;
      if (flist != null)
        if(j<0 )  {
          j = -1;
          lab.setText("no image");
        } else {

          while(j<flist.length)
          {
            if(flist[j].isFile())
            {
              if(flist[j].getName().toLowerCase().endsWith(".jpg"))
              {
                ig=new ImageIcon(fdial.getDirectory()+flist[j].getName());
                lab.setIcon(ig);
                b1.setEnabled(true);
                break;
              }
            }

            j--;
          }
        }
    }

    if(ae.getActionCommand().equals(" |> "))
    {
      ++j;

      if (flist != null)
        if(j>=flist.length){
          j = flist.length;
          lab.setText("no image");
        } else  {
          while(j<flist.length)
          {
            if(flist[j].isFile())
            {
              if(flist[j].getName().toLowerCase().endsWith(".jpg"))
              {
                ig=new ImageIcon(fdial.getDirectory()+flist[j].getName());
                lab.setIcon(ig);
                b1.setEnabled(true);
                break;

              }
            }

            j++;
          }
        }
    }



  }
  public static void main(String args[])
  {
    new picframe ();
  }

} 
Roman C
  • 49,761
  • 33
  • 66
  • 176
  • I'm not sure I'd conserned by the creation of a local reference to `FileDialog`, other then the fact that the OP really should be using a `JFileChooser` instead (if possible), rather then mixing heavy and light weight components - I would agree that there is a possibility for a bottle neck and a class level reference will probably provide better functionality though - IMHO – MadProgrammer Jan 12 '13 at 21:32
  • Yeah, OP probably should but I couldn't use it because it would be out of topic answer since with the difference in implementations and behavior, in the next question may be if OP has any questions but it seems forgotten here. – Roman C Jan 12 '13 at 22:44