我正在寻找一种方法来创建具有触摸滚动支持的 Java 触摸应用程序(不适用于移动设备)。到目前为止,我一直在搜索,我正在调查如何做到这一点 - 我发现的是 MT4J(http://www.mt4j.org/),但它似乎不支持这一点(如果我错了,请纠正我)。所以我的问题是,我如何在水平触摸/滑动时模拟滚动事件?
感谢帮助!亲切的问候,亚历克斯
我正在寻找一种方法来创建具有触摸滚动支持的 Java 触摸应用程序(不适用于移动设备)。到目前为止,我一直在搜索,我正在调查如何做到这一点 - 我发现的是 MT4J(http://www.mt4j.org/),但它似乎不支持这一点(如果我错了,请纠正我)。所以我的问题是,我如何在水平触摸/滑动时模拟滚动事件?
感谢帮助!亲切的问候,亚历克斯
这通过子类化 JScrollPane 实现了触摸和拖动滚动条。
因为触摸和拖动本身是不够的,所以我增加了动力,以便在释放鼠标按钮时“抛出”滚动。
卷轴的末端没有“反弹”,因为我无力为“反弹”的所有者打官司。
它没有完全封装,因为虽然视图是 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);
您可以使用JavaFX 的触摸事件框架。
以下是链接教程中有关处理滚动事件的一些示例代码:
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();
}
});