我想用 Java 制作一个滑块,类似于 JSlider,但它本身可以有多个滑块。确切地说,我想在 Microsoft Excel 中实现固定宽度功能中使用的滑块(从数据-> 固定宽度)。一个普通的滑块只有一个点,我们可以将它拖到不同的位置。现在,如果我在滑块的某个位置单击,应该添加一个新点,并且该点的拖动操作应该独立于之前的拖动操作。此外,如果我双击,该点将从滑块中删除。
问问题
436 次
1 回答
3
import java.awt.*;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.plaf.basic.BasicSliderUI;
public class MultiSlider extends JComponent
{
public static void main(String[] args)
{ // main method just for showing a usage example
try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); }
catch(Exception ex){}
JFrame f=new JFrame();
final MultiSlider slider = new MultiSlider();
slider.setValue(0, 80);
slider.addValue(20);
f.getContentPane().add(slider);
f.setSize(200, 100);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
public MultiSlider()
{
super.setLayout(null);
addSlider(0);
}
public void setValue(int slider, int value)
{
((JSlider)getComponent(slider)).setValue(value);
}
public void addValue(int value)
{
addSlider(value);
}
@Override
public boolean isOptimizedDrawingEnabled()
{
return false;
}
@Override
public void doLayout()
{
Insets i=getInsets();
int x=i.left, y=i.top, width=getWidth()-x-i.right, height=getHeight()-y-i.bottom;
for(int ix=0, n=getComponentCount(); ix<n; ix++)
getComponent(ix).setBounds(x, y, width, height);
}
class SubSlider extends JSlider
{
private SubSlider active;
@Override
protected void processMouseEvent(MouseEvent e)
{
SubSlider sl=getClosestSlider(e);
if(e.getID()==MouseEvent.MOUSE_PRESSED) active=sl;
else if(e.getID()==MouseEvent.MOUSE_RELEASED) active=null;
if(e.getID()==MouseEvent.MOUSE_CLICKED)
{
if(sl==null && e.getClickCount()==1) addSlider(e.getPoint());
else if(sl!=null && e.getClickCount()==2)
{
removeSlider(sl);
return;
}
}
if(sl!=null) sl.realProcessMouseEvent(e);
}
private void realProcessMouseEvent(MouseEvent e)
{
e.setSource(this);
super.processMouseEvent(e);
}
@Override
protected void processMouseMotionEvent(MouseEvent e)
{
if(e.getID()==MouseEvent.MOUSE_MOVED)
toAllSliders(e);
else
{
if(active==null) active=getClosestSlider(e);
if(active!=null) active.realProcessMouseMotionEvent(e);
}
}
private void realProcessMouseMotionEvent(MouseEvent e)
{
e.setSource(this);
super.processMouseMotionEvent(e);
}
}
final void toAllSliders(MouseEvent e)
{
for(int ix=0, n=getComponentCount(); ix<n; ix++)
((SubSlider)getComponent(ix)).realProcessMouseMotionEvent(e);
}
public void removeSlider(SubSlider sl)
{
if(getComponentCount()<=1) return;// must keep the last slider
remove(sl);
JSlider slider=(JSlider)getComponent(getComponentCount()-1);
slider.setOpaque(true);
slider.setPaintTrack(true);
revalidate();
repaint();
}
final SubSlider getClosestSlider(MouseEvent e)
{
SubSlider s=(SubSlider)getComponent(0);
BasicSliderUI bsUI=(BasicSliderUI)s.getUI();
int value = bsUI.valueForXPosition(e.getX());
if(Math.abs(s.getValue()-value)<=1) return s;
for(int ix=1, n=getComponentCount(); ix<n; ix++)
{
s=(SubSlider)getComponent(ix);
if(Math.abs(s.getValue()-value)<=1) return s;
}
return null;
}
void addSlider(Point point)
{
BasicSliderUI bsUI = (BasicSliderUI)((JSlider)getComponent(0)).getUI();
addSlider(bsUI.valueForXPosition(point.x));
}
void addSlider(int value)
{
final JSlider slider = new SubSlider();
slider.setFocusable(false);
slider.setValue(value);
if(getComponentCount()!=0)
{
slider.setOpaque(false);
slider.setPaintTrack(false);
}
super.add(slider, 0);
revalidate();
repaint();
}
}
于 2013-09-19T16:12:13.763 回答