Search code examples
javaswingtouchwindows-8.1tablet

Why does my AWT/swing GUI JAR capture stylus event data only in a specific region of the screen on a Windows 8.1 tablet?


QUESTION SUMMARY: I generated a .JAR file using Netbeans 7.2.1 for a Java Swing/AWT program developed on Windows 7 (Java version 1.8.0_40), that helps collect user handwriting from the screen. It runs fine on a Windows 7 notebook PC but due to some reason captures handwriting data only on a specific region of the screen on a Windows 8.1 tablet (Java version 1.8.0_45). Could someone kindly tell me why this is happening?

DETAILS: I have a requirement of collecting online handwriting samples (i.e. those acquired from electronic devices like a tablet PC using a pen/stylus and writing surface) for some analysis

Being new to developing programs of this nature, I read up about it on the web and decided to use the Java Swing/AWT toolkits

A person's handwriting is composed of strokes which are in turn composed of points. My objective was to capture: - the X- and Y-coordinates of a point on the screen - the timestamp of creation of this point - the stroke's start-time, end-time and color (color not too important)

To this end I wrote the following program using Netbeans 7.2.1 IDE with Java 1.8.0_40 on a Windows 7 Home Basic OS

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package handwritingsamplerawt;
import java.awt.AWTException;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class HandwritingSamplerAWT {
    static JFrame frame;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                CreateAndShowGUI(); 
            }
        });
    }

    private static void CreateAndShowGUI() {
        frame = new JFrame("Writing Surface v0.1");
        frame.getContentPane().setLayout(new FlowLayout(FlowLayout.RIGHT));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBackground(Color.LIGHT_GRAY);
        frame.pack();
        frame.add(new MyPanel());
        frame.setVisible(true);
    }
}

class MyPanel extends JPanel{
    private int x,y;
    static int strokeIndex;
    private long reducedMillis;
    private ArrayList<StrokeInfo> strokes;
    private JButton btnSave;



    public MyPanel() {
        MyPanel.strokeIndex=0;
        this.reducedMillis = 1435800000000L;
        this.strokes = new ArrayList<>();
        this.btnSave = new JButton("SAVE SAMPLE");
        this.btnSave.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                WriteCoordinates();
            }
        });
        this.add(this.btnSave);

        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                x=e.getX();
                y=e.getY();
                SaveCoordinates(x,y,"PRESSED");
                repaint();
            }
        });

        addMouseMotionListener(new MouseAdapter() {
            public void mouseDragged(MouseEvent e) {
                x=e.getX();
                y=e.getY();
                SaveCoordinates(x,y,"DRAGGED");
                repaint();
            }
        });

        addMouseListener(new MouseAdapter() {
            public void mouseReleased(MouseEvent e) {
                x=e.getX();
                y=e.getY();
                SaveCoordinates(x,y,"RELEASED");
                repaint();
            }
        });
    }

    void SaveCoordinates(int xCoordinate, int yCoordinate, String actionIndicator){
        try {
            Calendar cal = Calendar.getInstance();
            Date currDate = cal.getTime();
            double timeStamp=(double)(currDate.getTime()-reducedMillis);
            PointInfo pointObj = new PointInfo(xCoordinate, yCoordinate, timeStamp);
            switch (actionIndicator) {
                case "PRESSED":
                    StrokeInfo newStroke = new StrokeInfo();
                    newStroke.points.add(pointObj);
                    strokes.add(newStroke);
                    break;
                case "DRAGGED":
                    strokes.get(strokeIndex).points.add(pointObj);
                    break;
                case "RELEASED":
                    strokeIndex+=1;
                    break;
            }
        } catch (Exception ex){
            String errMsg = ex.getMessage();
            System.out.println(errMsg);
        }
    }

    void WriteCoordinates() {
        try {
            Calendar cal = Calendar.getInstance();
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
            String currTimeString = dateFormat.format(cal.getTime());

            DecimalFormat decFormat = new DecimalFormat("#");
            decFormat.setMaximumFractionDigits(2);
            FileWriter writer = new FileWriter("D:\\HandwritingCaptures\\HandwritingText\\"+currTimeString+".txt");
            SetStrokeAttributes(strokes);
            ListIterator<PointInfo> pointItr;
            if (strokes.isEmpty()==false) {
                for (int index = 0; index < strokeIndex; index++) {
                    writer.write(strokes.get(index).colour);
                    writer.append('\t');
                    writer.write(decFormat.format( strokes.get(index).startTime));
                    writer.append('\t');
                    writer.write(decFormat.format( strokes.get(index).endTime));
                    writer.append('\n');
                    pointItr = strokes.get(index).points.listIterator();
                    while (pointItr.hasNext()) {
                        PointInfo currPoint = pointItr.next();
                        writer.write(String.valueOf(currPoint.x));
                        writer.append('\t');
                        writer.write(String.valueOf(currPoint.y));
                        writer.append('\t');
                        writer.write(decFormat.format(currPoint.timestamp));
                        writer.append('\n');
                    }
                    writer.append('#');
                    writer.append('\n');
                }
            }
            writer.close();

            SaveScreenshot("D:\\HandwritingCaptures\\Screenshots\\"+currTimeString+".png");
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }

    void SetStrokeAttributes(ArrayList<StrokeInfo> strokeList) {
        double startTime, endTime;
        String colour;
        StrokeInfo tmpStroke;
        ArrayList<PointInfo> points;
        if (strokeList.isEmpty() == false) {
            for (int index = 0; index < strokeList.size(); index++) {
                tmpStroke = strokeList.get(index);
                points = tmpStroke.points;
                tmpStroke.colour = "black";
                tmpStroke.startTime=points.get(0).timestamp;
                tmpStroke.endTime=points.get(points.size()-1).timestamp;
                strokeList.set(index, tmpStroke);
            }
        }
    }

    void SaveScreenshot(String imgFilePath){
        try {
            Rectangle screenRect = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
            BufferedImage capture = new Robot().createScreenCapture(screenRect);
            ImageIO.write(capture, "png", new File(imgFilePath));
        } catch (IOException | AWTException ex) {
            System.out.println(ex.getMessage());
        }
    }

    public Dimension getPreferredSize() {
        return new Dimension(1366,768);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponents(g);
        g.setColor(Color.BLACK);
        g.drawLine(x, y, x, y);
    }
}

class PointInfo {
    int x,y;
    double timestamp;

    public PointInfo(int px, int py, double ts) {
        this.x=px;
        this.y=py;
        this.timestamp=ts;
    }
}

class StrokeInfo {
    ArrayList<PointInfo> points;
    double startTime, endTime;
    String colour;
    public StrokeInfo() {
        points= new ArrayList<>();
    }
}

I generated the .jar file using the IDE itself (Project Properties-> Build-> Packaging-> Compress JAR file)

Then copied the .jar file to a HP EliteBook 2730P Notebook PC with JRE 1.7.0.800 and Windows 7 Pro OS (32-bit) where it ran fine collecting handwriting strokes from all areas of the screen

But when I copied the same .jar to a HP Elite x2 1011 G1 tablet with JRE 1.8.0_45 and Windows 8.1 (64-bit) and ran it, I found that strangely it captures stylus inputs ONLY from a specific region of the screen - more specifically towards the upper right. It is completely non-responsive on the other areas

Could someone please help me understand why this is happening? Would have posted couple screenshots here but my low reputation prevents me from doing so.

ADDITIONAL THOUGHTS: Would it be better to use .NET or Java FX for developing such a tool for using in a Windows 8.1 environment?


Solution

  • Your panel seems to have a fixed size:

    return new Dimension(1366,768);
    

    Is the resolution of your tablet bigger than that?

    Edit:

    This should help:

    private static void CreateAndShowGUI() {
        frame = new JFrame("Writing Surface v0.1");
        // Using the default BorderLayout here.
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBackground(Color.LIGHT_GRAY);
        frame.getContentPane().add(new MyPanel(), BorderLayout.CENTER);
        frame.pack();
        frame.setVisible(true);
    }
    

    However there are still problems with your layout, like the "Save" button jumping around. You should take a look at this tutorial:

    https://docs.oracle.com/javase/tutorial/uiswing/layout/index.html