【问题标题】:Emulate touch scroll in Java在 Java 中模拟触摸滚动
【发布时间】:2013-05-09 20:34:10
【问题描述】:

我正在寻找一种在 Java 中创建具有触摸滚动支持的触摸应用程序的方法(不适用于移动设备)。 到目前为止,我一直在搜索,我正在调查如何做到这一点 - 我发现的是 MT4J (http://www.mt4j.org/),但它似乎不支持这一点(如果我错了,请纠正我)。 所以我的问题是,如何在水平触摸/滑动时模拟滚动事件?

感谢您的帮助! 亲切的问候, 亚历克斯

【问题讨论】:

    标签: java touch javafx desktop-application


    【解决方案1】:

    这通过子类化 JScrollPane 来实现触摸和拖动滚动器。

    因为仅靠触摸和拖动是不够的,所以我增加了动力 以便在释放鼠标按钮时“抛出”滚动条。

    卷轴末端没有“反弹”,因为我负担不起 与“bounce”的所有者打官司。

    它没有完全封装,因为虽然它可以正常工作 视图是一个jlist,视图上可能有需要的组件 如果当时正在拖动面板,则修改他们的响应。 还有一些组件,例如JRadioButton、JCheckBox 等消费 鼠标单击而不将它们传递给容器,因此您将 需要给它们添加TouchScroll的MouseListener和MouseMotionListener。

    import java.awt.Component;
    import java.awt.event.MouseEvent;
    import java.awt.event.MouseListener;
    import java.awt.event.MouseMotionListener;
    
    import javax.swing.JScrollBar;
    import javax.swing.JScrollPane;
    
    public class TouchScroll extends JScrollPane implements MouseListener,   MouseMotionListener {
    private JScrollBar vbar = this.getVerticalScrollBar();
    
    public TouchScroll(Component view){ // 1-arity CONSTRUCTOR
        super(view);
        view.addMouseListener(this);
        view.addMouseMotionListener(this);
    }
    public TouchScroll() {  super();    }   // 0-arity CONSTRUCTOR
    
    public void setViewportView(Component view) {
        super.setViewportView(view);
        view.addMouseListener(this);
        view.addMouseMotionListener(this);
    }
    
    private static boolean wasdragged = false;  // other MouseListeners may need to know this ...
    public boolean wasDragged() {       return wasdragged;  }   // ... this gives them safe access
    
    static int lastY = 0, distY = 0;
    double momentum = 0;    // not really physical momentum but it will be used to 'throw' the scroll when the mouse button is released
    static boolean lbdown = false;
    @Override
    public void mouseDragged(MouseEvent e) {
        wasdragged = true;      
        distY = 0;
        int currentY = e.getYOnScreen();
        if(lbdown) {
            distY =  lastY - currentY;
            vbar.setValue(distY + vbar.getValue());
            if(Math.abs(distY) > 1)
                momentum = distY + distY;   // magnify and log the momentum for later use
        }
        lastY = currentY;
    }
    
    @Override
    public void mousePressed(MouseEvent e) {
        if (e.getButton() == MouseEvent.BUTTON1) {
            lastY = e.getYOnScreen();
            lbdown = true;
        }
    }
    
    @Override
    public void mouseReleased(MouseEvent e) {
        if (e.getButton() == MouseEvent.BUTTON1)
            lbdown = false;
        if(wasdragged)
            wasdragged = false;
    
        if(Math.abs(momentum) <= 4.0)   // then assume that the mouse wasn't moving (much) when the button was released
            return;
        // otherwise 'throw' the scroll
        int max = vbar.getMaximum();
        int count;
        double brakingforce = 1.04;     // set an initial braking force
        for(count = 1000; count > 0; count--){  // don't allow it to accidentally go on forever
            momentum = momentum / brakingforce; // apply the brake
            if(Math.abs(momentum) < 1.5)
                brakingforce = 1.02;    // ease off the brake towards the end (gives a slight overrun ala iOS)
            if(Math.abs(momentum) < 1.0)    // bring it to a halt
                break;
            int val = vbar.getValue();
            if(val < 0 || val > max)    // prevent overrun
                break;
            vbar.setValue((int) momentum + val);    // increment the scroll bar
            try {
                Thread.sleep(10);       // slow the loop down so the user can see the scroll
            } catch (InterruptedException e1) {
                e1.printStackTrace();
            }
        }
    }
    
    public void mouseMoved(MouseEvent e) {}
    public void mouseClicked(MouseEvent e) {}
    public void mouseEntered(MouseEvent e) {}
    public void mouseExited(MouseEvent e) {}
    

    }

    下面是一个“基本”示例,说明如何应用它:

    panel = new JPanel();
    jlist = new JList(list);
    scroller = new TouchScroll(jlist);
    panel.add(scroller);
    

    响应鼠标释放的任何组件都可能需要执行以下操作:

    public void mouseReleased(MouseEvent e) {   
        if(scroller.wasDragged())
            return;
        actionENTER();
    }
    

    最后,如前所述,消耗鼠标事件的组件将需要 像这样通知滚动条:

    JCheckBox checkbox = new JCheckBox(text);
    checkbox.addMouseMotionListener(scroller);
    checkbox.addMouseListener(scroller);
    

    【讨论】:

      【解决方案2】:

      您可以使用JavaFX's touch event framework

      以下是链接教程中有关处理滚动事件的一些示例代码:

      rect.setOnScroll(new EventHandler<ScrollEvent>() {
              @Override public void handle(ScrollEvent event) {
                  if (!event.isInertia()) {
                      rect.setTranslateX(rect.getTranslateX() + event.getDeltaX());
                      rect.setTranslateY(rect.getTranslateY() + event.getDeltaY());
                  }
                  log("Rectangle: Scroll event" +
                      ", inertia: " + event.isInertia() + 
                      ", direct: " + event.isDirect());
                  event.consume();
              }
      });
      
      rect.setOnScrollStarted(new EventHandler<ScrollEvent>() {
              @Override public void handle(ScrollEvent event) {
                  inc(rect);
                  log("Rectangle: Scroll started event");
                  event.consume();
              }
      });
      
      rect.setOnScrollFinished(new EventHandler<ScrollEvent>() {
              @Override public void handle(ScrollEvent event) {
                  dec(rect);
                  log("Rectangle: Scroll finished event");
                  event.consume();
              }
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多