为什么我的 AWT/swing GUI JAR 只能在 Windows 8.1 平板电脑屏幕的特定区域捕获手写笔事件数据?

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?

问题摘要: 我使用 Netbeans 7.2.1 为在 Java Swing/AWT 上开发的程序生成了一个 .JAR 文件=55=] 7(Java 1.8 版。0_40),有助于从屏幕上收集用户笔迹。它在 Windows 7 笔记本电脑上运行良好,但由于某种原因只能在 Windows 8.1 平板电脑(Java 版本 1.8.[=45] 上捕获屏幕特定区域的手写数据=]).有人可以告诉我为什么会这样吗?

详情: 我需要收集一些在线手写样本(即从使用 pen/stylus 和书写表面的平板电脑等电子设备获取的手写样本)分析

作为开发这种性质的程序的新手,我在网上阅读了它并决定使用 Java Swing/AWT 工具包

一个人的笔迹是由笔画组成的,而笔画又是由点组成的。我的 objective 是要捕获: - 屏幕上某个点的 X 和 Y 坐标 - 创建该点的时间戳 - 笔划的开始时间、结束时间和颜色(颜色不太重要)

为此,我使用 Netbeans 7.2.1 IDE 和 Java 1.8.0_40 在 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<>();
    }
}

我使用 IDE 本身生成了 .jar 文件(项目属性-> 构建-> 打包-> 压缩 JAR 文件)

然后将 .jar 文件复制到装有 JRE 1.7.0.800 和 Windows 7 Pro OS(32 位)的 HP EliteBook 2730P 笔记本电脑,它 运行 很好地收集了来自屏幕所有区域的手写笔画

但是当我将相同的 .jar 复制到带有 JRE 1.8 的 HP Elite x2 1011 G1 平板电脑时。0_45 和 Windows 8.1(64 位)和 运行 它,我发现 st运行gely 它仅从屏幕的特定区域捕获手写笔输入 - 更具体地说是右上角。其他区域完全没有反应

有人可以帮我理解为什么会这样吗?本来可以在这里张贴几个屏幕截图,但我的低声誉阻止我这样做。

其他想法:使用 .NET 或 Java FX 来开发这样一个在 Windows 8.1 环境中使用的工具会更好吗?

您的面板似乎有固定大小:

return new Dimension(1366,768);

你平板电脑的分辨率比那个大吗?

编辑:

这应该有帮助:

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);
}

但是您的布局仍然存在问题,例如 "Save" 按钮跳来跳去。你应该看看这个教程:

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

在 运行ning

上看到 .jar 文件的行为后,问题可能与硬编码维度有关的事实变得很清楚

平板电脑的分辨率(1920 x 1080 像素 - 通过右键单击桌面检查屏幕分辨率发现)比我最初 运行 程序所在的机器(1366 x 768 像素)更高).可写区域朝向右上角的尺寸实际上与硬编码尺寸一致

因此,我按以下方式修改了覆盖方法 getPreferredSize()

public Dimension getPreferredSize() {
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        return new Dimension((int)screenSize.getWidth(),(int)screenSize.getHeight());
    }

这会导致首选尺寸的组件占据执行 .jar 的设备屏幕的有效高度和宽度。这很重要,因为根据所使用的布局管理器,它对上述方法的处理确实不同

"SAVE SAMPLE" 按钮似乎仍会间歇性地将其图像(不可点击)投射到屏幕的其他区域 - 这可能与 UI 的布局管理器处理有关组件。找到解决方案后,也应为该问题添加编辑