0

Desired functionality: Listen for line-delineated barcode scans (a string of characters). For each pair (always scanned in the same order, one is longer than the other), compare the two for equality. If they are the same, display an image. If they are different, display another image. Repeat infinitely until window is closed.

In my head, there are two modules to this program. One is constantly looping, taking in the strings, comparing, and sending out a result (== or !=). The other just waits for the result, displays the appropriate image, and waits for the next comparison result.

The code I have is below, and I can't wrap my head around how to get repaint() to work properly at the end of each loop (once the result of the comparison is known). I have tried push out the result to the MyFrame Class and have it repaint() there and I have tried to call repaint() in the loop, but that won't work either.

The ScannerCompare Class works by itself in the console, but that won't be very useful for my intended implementation. If only the System.out.println("OK") and ("NG") were pictures!

Many thanks!

package BarcodeVerification;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.WindowConstants;


public class MyFrame extends JFrame {

private Image ngImage = null;
private Image okImage = null;

public MyFrame(String ngFilename, String okFilename) {
    setTitle("MyWindow");
    setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    setSize(800, 600);

    this.ngImage = new ImageIcon(ngFilename).getImage();
    this.okImage = new ImageIcon(okFilename).getImage();

    Container container = getContentPane();
    container.setLayout(new BorderLayout());

}

@Override
public void paint(Graphics g) {
    super.paint(g);

    if (m.getResult()) {
        g.drawImage(okImage, 0, 0, okImage.getWidth(null), okImage.getHeight(null), null);
    }
    else {
        g.drawImage(ngImage, 0, 0, ngImage.getWidth(null), ngImage.getHeight(null), null);
    }
}

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {

        @Override
        public void run() {
            MyFrame frame = new MyFrame("src/NG.png","src/OK/png");
            ScannerCompare m = new ScannerCompare();
            frame.setVisible(true);
        }

    });
}
}



package BarcodeVerification;

import java.util.Scanner;


public class ScannerCompare {

public Boolean ok;
public String scan1, scan2, injectorExtract;

public ScannerCompare (){
Scanner in = new Scanner(System.in);

    while (true) {
        System.out.println("Scan the paper");
        scan1 = in.nextLine();

        System.out.println("Scan the Injector QR Code");
        scan2 = in.nextLine();

        injectorExtract = scan2.substring(19);

        if (scan1.compareTo(injectorExtract) != 0) {
            System.out.println("NG");
            ok = false;
            repaint();
        } else {
            System.out.println("OK");
            ok = true;
            repaint()
        }
    }
}
public boolean getResult(){
    return ok;
}
}
Erik Olson
  • 383
  • 1
  • 3
  • 11
  • What connection does `ScannerCompare` have to `MyFrame`? How can `ScannerCompare` influence any instance of `MyFrame`? – MadProgrammer Nov 25 '15 at 00:12
  • Don't override `paint` of top level containers like `JFrame`, instead, start with component like `JPanel` and override it's `paintComponent` method instead. See [this](http://stackoverflow.com/questions/13734069/how-can-i-set-in-the-midst/13734319#13734319) for at least one reason why you shouldn't override `paint` of a top level container – MadProgrammer Nov 25 '15 at 00:14
  • You might want to also have a look at [Worker Threads and SwingWorker](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html) – MadProgrammer Nov 25 '15 at 00:15
  • I've tried to create a ScannerCompare object in the MyFrame, and from there call a getResult() method, but that didn't work either. Just edited the end of ScannerCompare and if statement in paint to reflect this. – Erik Olson Nov 25 '15 at 00:18

1 Answers1

1

You basic problem can be solved using an Observer Pattern.

The "scanner" checks the results of the scans and generates some kind of event/notification to registered/interested observers/listeners

Swing is a single threaded framework, so you can't simply place a while (true) in your code as it may block the Event Dispatching Thread, preventing it from processing any events, including paint events. See Concurrency in Swing for more details.

You could use a SwingWorker to over come this limitation, allowing the doInBackground method to process the scans and the publish/process methods to trigger the notifications within the context of the EDT safely, see Worker Threads and SwingWorker for more details

As a proof of concept...

import java.awt.BorderLayout;
import javax.swing.ImageIcon;
import java.awt.EventQueue;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
import java.util.Scanner;
import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class Scanny {

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

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

                try {
                    BufferedImage empty = ImageIO.read(...);
                    BufferedImage good = ImageIO.read(...);
                    BufferedImage bad = ImageIO.read(...);

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(new ScannerPane(new ImageIcon(empty), new ImageIcon(good), new ImageIcon(bad)));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public class ScannerPane extends JPanel {

        private JLabel label;
        private Icon empty;
        private Icon good;
        private Icon bad;

        public ScannerPane(Icon empty, Icon good, Icon bad) {
            setLayout(new BorderLayout());
            this.empty = empty;
            this.good = good;
            this.bad = bad;

            label = new JLabel(empty, JLabel.CENTER);
            add(label);

            ScannerWorker worker = new ScannerWorker(new ScannerObserver() {
                @Override
                public void scanWasGood() {
                    label.setIcon(good);
                }

                @Override
                public void scanWasBad() {
                    label.setIcon(bad);
                }
            });
            worker.execute();
        }

    }

    public interface ScannerObserver {
        public void scanWasGood();
        public void scanWasBad();
    }

    public class ScannerWorker extends SwingWorker<Void, Boolean> {

        private ScannerObserver observer;

        public ScannerWorker(ScannerObserver observer) {
            this.observer = observer;
        }

        @Override
        protected Void doInBackground() throws Exception {
            Scanner in = new Scanner(System.in);

            while (true) {
                String scan1 = in.nextLine();
                String scan2 = in.nextLine();

                String injectorExtract = scan2.substring(19);

                if (scan1.compareTo(injectorExtract) != 0) {
                    publish(Boolean.TRUE);
                } else {
                    publish(Boolean.FALSE);
                }
            }
        }

        @Override
        protected void process(List<Boolean> chunks) {
            boolean last = chunks.get(chunks.size() - 1);
            if (last) {
                observer.scanWasGood();
            } else {
                observer.scanWasBad();
            }
        }

    }

}

See Reading/Loading an Image for more details about ImageIO

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Thank you! Lots of reverse engineering to do... However, the image will not switch. Before, I could type in a string, press enter (emulating what the barcode scanner does), and I would get a result. – Erik Olson Nov 25 '15 at 01:03
  • Thank you again - you've done all of the work and to you I owe the credit. Now, when I create and execute the jar, [link](http://imgur.com/8AuT0bR) this happens. Ideas? The program works perfectly in Intellij... – Erik Olson Nov 25 '15 at 21:03
  • Tried implementing this change using `BufferedImage empty = ImageIO.read(this.getClass().getClassLoader().getResource("startScreen.png"));` instead, still no beans. [here](http://imgur.com/9x9fQgn) is the output using that method. – Erik Olson Nov 25 '15 at 21:12
  • The images are not been included in your Jar file – MadProgrammer Nov 25 '15 at 21:38