Java 当鼠标悬停在JTable上时滚动JPanel
我在Java 当鼠标悬停在JTable上时滚动JPanel,java,swing,jpanel,jscrollpane,mousewheel,Java,Swing,Jpanel,Jscrollpane,Mousewheel,我在JPanel中有一个JTable。我可以使用鼠标滚轮上下滚动JPanel,但当我的鼠标悬停在JTable上时,我必须将其移出表格,使用滚轮向上滚动JPanel。如果鼠标悬停在JTable上,是否可以使用滚轮上下滚动JPanel 我在上面的评论中采纳了Xeon的建议,并实现了一个鼠标滚轮侦听器,将鼠标滚轮事件转发给父组件。请参阅下面的代码 public class CustomMouseWheelListener implements MouseWheelListener { priva
JPanel
中有一个JTable
。我可以使用鼠标滚轮上下滚动JPanel
,但当我的鼠标悬停在JTable
上时,我必须将其移出表格,使用滚轮向上滚动JPanel
。如果鼠标悬停在JTable
上,是否可以使用滚轮上下滚动JPanel
我在上面的评论中采纳了Xeon的建议,并实现了一个鼠标滚轮侦听器,将鼠标滚轮事件转发给父组件。请参阅下面的代码
public class CustomMouseWheelListener implements MouseWheelListener {
private JScrollBar bar;
private int previousValue = 0;
private JScrollPane parentScrollPane;
private JScrollPane customScrollPane;
/** @return The parent scroll pane, or null if there is no parent. */
private JScrollPane getParentScrollPane() {
if (this.parentScrollPane == null) {
Component parent = this.customScrollPane.getParent();
while (!(parent instanceof JScrollPane) && parent != null) {
parent = parent.getParent();
}
this.parentScrollPane = (JScrollPane) parent;
}
return this.parentScrollPane;
}
/**
* Creates a new CustomMouseWheelListener.
* @param customScrollPane The scroll pane to which this listener belongs.
*/
public CustomMouseWheelListener(JScrollPane customScrollPane) {
ValidationUtils.checkNull(customScrollPane);
this.customScrollPane = customScrollPane;
this.bar = this.customScrollPane.getVerticalScrollBar();
}
/** {@inheritDoc} */
@Override
public void mouseWheelMoved(MouseWheelEvent event) {
JScrollPane parent = getParentScrollPane();
if (parent != null) {
if (event.getWheelRotation() < 0) {
if (this.bar.getValue() == 0 && this.previousValue == 0) {
parent.dispatchEvent(cloneEvent(event));
}
}
else {
if (this.bar.getValue() == getMax() && this.previousValue == getMax()) {
parent.dispatchEvent(cloneEvent(event));
}
}
this.previousValue = this.bar.getValue();
}
else {
this.customScrollPane.removeMouseWheelListener(this);
}
}
/** @return The maximum value of the scrollbar. */
private int getMax() {
return this.bar.getMaximum() - this.bar.getVisibleAmount();
}
/**
* Copies the given MouseWheelEvent.
*
* @param event The MouseWheelEvent to copy.
* @return A copy of the mouse wheel event.
*/
private MouseWheelEvent cloneEvent(MouseWheelEvent event) {
return new MouseWheelEvent(getParentScrollPane(), event.getID(), event.getWhen(),
event.getModifiers(), 1, 1, event.getClickCount(), false, event.getScrollType(),
event.getScrollAmount(), event.getWheelRotation());
}
}
公共类CustomMouseWheelListener实现MouseWheelListener{
私人酒吧;
private int previousValue=0;
私有JScrollPane parentScrollPane;
私有JScrollPane自定义滚动窗格;
/**@返回父滚动窗格,如果没有父滚动窗格,则返回null*/
私有JScrollPane getParentScrollPane(){
if(this.parentScrollPane==null){
组件父级=this.customScrollPane.getParent();
而(!(JScrollPane的父实例)&&parent!=null){
parent=parent.getParent();
}
this.parentScrollPane=(JScrollPane)父级;
}
返回此.parentScrollPane;
}
/**
*创建新的CustomMouseWheelListener。
*@param customScrollPane此侦听器所属的滚动窗格。
*/
公共CustomMouseWheelListener(JScrollPane customScrollPane){
ValidationUtils.checkNull(customScrollPane);
this.customScrollPane=customScrollPane;
this.bar=this.customScrollPane.getVerticalScrollBar();
}
/**{@inheritardoc}*/
@凌驾
公共作废mouseWheelMoved(MouseWheelEvent事件){
JScrollPane parent=getParentScrollPane();
如果(父项!=null){
if(event.getWheelRotation()<0){
if(this.bar.getValue()==0&&this.previousValue==0){
父调度事件(cloneEvent(事件));
}
}
否则{
if(this.bar.getValue()==getMax()&&this.previousValue==getMax()){
父调度事件(cloneEvent(事件));
}
}
this.previousValue=this.bar.getValue();
}
否则{
this.customScrollPane.removeMouseWheelListener(this);
}
}
/**@返回滚动条的最大值*/
私有int getMax(){
返回this.bar.getMaximum()-this.bar.getVisibleMount();
}
/**
*复制给定的MouseWheelEvent。
*
*@param event要复制的MouseWheelEvent。
*@返回鼠标滚轮事件的副本。
*/
专用MouseWheelEvent克隆事件(MouseWheelEvent事件){
返回新的MouseWheelEvent(getParentScrollPane(),event.getID(),event.GetWheel(),
event.getModifiers(),1,1,event.getClickCount(),false,event.getScrollType(),
event.getScrollAmount(),event.getWheelRotation();
}
}
感谢邓绍托克分享您的代码。我已经按照同样的思路实现了一个解决方案(事件转发),但直接将其放到滚动窗格中。我想这可能对其他人有用
/**
* Scroll pane that only scrolls when it owns focus. When not owning focus (i.e. mouse
* hover), propagates mouse wheel events to its container.
* <p>
* This is a solution for <i>"I have a JTable inside a JPanel. When my mouse is hovering
* over the JTable, I have to move it out of the table to scroll the JPanel."</i>
*/
public class ScrollWhenFocusedPane extends JScrollPane {
// Note: don't leave users with "scroll on focus" behaviour
// on widgets that they cannot focus. These will be okay.
public ScrollWhenFocusedPane (JTree view) {super (view);}
public ScrollWhenFocusedPane (JList view) {super (view);}
public ScrollWhenFocusedPane (JTable view) {super (view);}
public ScrollWhenFocusedPane (JTextArea view) {super (view);}
@Override
protected void processMouseWheelEvent (MouseWheelEvent evt) {
Component outerWidget = SwingUtilities.getAncestorOfClass (Component.class, this);
// Case 1: we don't have focus, so we don't scroll
Component innerWidget = getViewport().getView();
if (!innerWidget.hasFocus())
outerWidget.dispatchEvent(evt);
// Case 2: we have focus
else {
JScrollBar innerBar = getVerticalScrollBar();
if (!innerBar.isShowing()) // Deal with horizontally scrolling widgets
innerBar = getHorizontalScrollBar();
boolean wheelUp = evt.getWheelRotation() < 0;
boolean atTop = (innerBar.getValue() == 0);
boolean atBottom = (innerBar.getValue() == (innerBar.getMaximum() - innerBar.getVisibleAmount()));
// Case 2.1: we've already scrolled as much as we could
if ((wheelUp & atTop) || (!wheelUp & atBottom))
outerWidget.dispatchEvent(evt);
// Case 2.2: we'll scroll
else
super.processMouseWheelEvent (evt);
}
}
}
/**
*仅在拥有焦点时滚动的滚动窗格。不拥有焦点时(即鼠标
*悬停),将鼠标滚轮事件传播到其容器。
*
*这是一个解决方案,“当我的鼠标悬停时,我在JPanel中有一个JTable
*在JTable上,我必须将其移出表以滚动JPanel。”
*/
公共类ScrollWhenFocusedPane扩展了JScrollPane{
//注意:不要让用户有“焦点滚动”行为
//在他们无法聚焦的小部件上。这些都可以。
公共滚动焦点窗格(JTree视图){super(视图);}
公共滚动焦点窗格(JList视图){super(视图);}
公共滚动焦点窗格(JTable视图){super(视图);}
公共滚动焦点窗格(JTextArea视图){super(视图);}
@凌驾
受保护的无效进程MouseWheelEvent(MouseWheelEvent evt){
Component outerWidget=SwingUtilities.getAncestorOfClass(Component.class,this);
//案例1:我们没有焦点,所以不能滚动
组件innerWidget=getViewport().getView();
如果(!innerWidget.hasFocus())
outerWidget.dispatchEvent(evt);
//案例2:我们有焦点
否则{
JScrollBar innerBar=getVerticalScrollBar();
if(!innerBar.isShowing())//处理水平滚动的小部件
innerBar=getHorizontalScrollBar();
布尔wheelUp=evt.getWheelRotation()<0;
布尔值atTop=(innerBar.getValue()==0);
底部布尔值=(innerBar.getValue()==(innerBar.getMaximum()-innerBar.getVisibleMount());
//案例2.1:我们已经尽可能多地滚动了
如果((车轮上升和倾斜)| |(!车轮上升和倾斜))
outerWidget.dispatchEvent(evt);
//案例2.2:我们将滚动
其他的
super.processMouseWheelEvent(evt);
}
}
}
我刚刚实现了您描述的案例,但是如果鼠标指针在JTable
上,我可以滚动JPanel
事件。您可以发布SSCCE吗?但基本上,您可以将滚轮滚动事件(mouseweelllistener
)转发到JPanel
的JScrollPane
,或者(可以是可伸缩的)使用事件来源:-),以便更快地发布更好的帮助(如果根本问题不是由JTable引起的,而是Swing bug)。也许是复制品。