How can I make a JSlider in a curve shape?

Joe Schofield

I want to create a Java Application for my parent's Estate Agency holiday let online booking service.

Unfortunately I can't yet post images but they want a kind of slider style booking service in which the user slides the bar to select price, bedrooms etc. The design they have given me uses curved sliders but I can't seem to find any help online. They want 5 sliders in a circle which displays the selected figures and has a button to confirm.

Does anyone have any ideas? Would it involve drawing a circular curve or something like that? Also is it going to be more trouble than it's worth - after all there are online alternative booking systems but it would be nice to have a bespoke one created.

Thanks for you help.

Marco13

When it comes to GUI components and the details of their look and style and behavior and intended usage, there usualy are infinitely many degrees of freedom.

Should this be solved with a dedicated look and feel? Should it be possible to influence the colors? The width of the "knob"? The start- and end angles of the curve? Would you like to have BoundedRangeModel in the background, to use it as a drop-in-replacement for a JSlider? ....

However, I wrote a very simple sketch, solely based on own painting and mouse listeners: One can modify the minimum- and maximum angles and values, and drag the knob with the mouse.

Due to the lack of details, it is not clear whether this is an appropriate solution for you. It does not have a `BoundedRangeModel´. It does not support listeners (although this would be the easiest to add). There may be some glitches concerning the behavior for border cases, and the solution for these will depend on details that you simply did not specify.

This is what it looks like:

CurvedSlider

The code as a MCVE:

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Arc2D;
import java.awt.geom.Area;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.io.IOException;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;


public class CurvedSliderTest
{
    public static void main(String[] args) throws IOException
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            @Override
            public void run()
            {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        f.getContentPane().setLayout(new BorderLayout());

        CurvedSlider gaugePanel = new CurvedSlider();
        f.getContentPane().add(gaugePanel, BorderLayout.CENTER);

        JPanel controlPanel = createControlPanel(gaugePanel);
        f.getContentPane().add(controlPanel, BorderLayout.NORTH);

        f.setSize(600,800);
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    static JPanel createControlPanel(final CurvedSlider gaugePanel)
    {
        final JSlider minAngleSlider = new JSlider(0, 100, 0);
        final JSlider maxAngleSlider = new JSlider(0, 100, 0);
        final JSlider minValueSlider = new JSlider(0, 100, 0);
        final JSlider maxValueSlider = new JSlider(0, 100, 0);
        final JSlider valueSlider = new JSlider(0, 100, 0);

        JPanel controlPanel = new JPanel(new GridLayout(0,2));
        controlPanel.add(new JLabel("minAngle"));
        controlPanel.add(minAngleSlider);
        controlPanel.add(new JLabel("maxAngle"));
        controlPanel.add(maxAngleSlider);
        controlPanel.add(new JLabel("minValue"));
        controlPanel.add(minValueSlider);
        controlPanel.add(new JLabel("maxValue"));
        controlPanel.add(maxValueSlider);
        controlPanel.add(new JLabel("value"));
        controlPanel.add(valueSlider);

        ChangeListener changeListener = new ChangeListener()
        {
            @Override
            public void stateChanged(ChangeEvent e)
            {
                double minAngle = minAngleSlider.getValue() / 100.0 * Math.PI * 2;
                double maxAngle = maxAngleSlider.getValue() / 100.0 * Math.PI * 2;
                double minValue = minValueSlider.getValue() / 100.0;
                double maxValue = maxValueSlider.getValue() / 100.0;
                double value = valueSlider.getValue() / 100.0;

                gaugePanel.setAngles(minAngle, maxAngle);
                gaugePanel.setRange(minValue, maxValue);
                gaugePanel.setValue(value);
            }
        };
        minAngleSlider.addChangeListener(changeListener);
        maxAngleSlider.addChangeListener(changeListener);
        minValueSlider.addChangeListener(changeListener);
        maxValueSlider.addChangeListener(changeListener);
        valueSlider.addChangeListener(changeListener);

        minAngleSlider.setValue(50);
        maxAngleSlider.setValue(0);
        minValueSlider.setValue(10);
        maxValueSlider.setValue(90);
        valueSlider.setValue(50);

        return controlPanel;
    }


}



class CurvedSlider extends JPanel implements MouseListener, MouseMotionListener
{
    private double minAngleRad = 0.0;
    private double maxAngleRad = 0.0;
    private double minValue = 0.0;
    private double maxValue = 0.0;
    private double value = 0.0;

    CurvedSlider()
    {
        addMouseListener(this);
        addMouseMotionListener(this);
    }

    void setAngles(double minAngleRad, double maxAngleRad)
    {
        this.minAngleRad = minAngleRad;
        this.maxAngleRad = maxAngleRad;
        repaint();
    }

    void setRange(double minValue, double maxValue)
    {
        this.minValue = minValue;
        this.maxValue = maxValue;
        repaint();
    }

    void setValue(double value)
    {
        this.value = value;
        repaint();
    }

    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        g.setRenderingHint(
            RenderingHints.KEY_ANTIALIASING, 
            RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(Color.WHITE);
        g.fillRect(0,0,getWidth(),getHeight());

        boolean printValues = false;
        printValues = true;
        if (printValues)
        {
            int ty = 20;
            g.setColor(Color.BLACK);
            g.drawString("minAngle "+Math.toDegrees(minAngleRad), 20, ty+=20);
            g.drawString("maxAngle "+Math.toDegrees(maxAngleRad), 20, ty+=20);
            g.drawString("minValue "+minValue, 20, ty+=20);
            g.drawString("maxValue "+maxValue, 20, ty+=20);
            g.drawString("value "+value, 20, ty+=20);
        }

        double alpha = (value - minValue) / (maxValue - minValue);
        double angleRad = minAngleRad + alpha * (maxAngleRad - minAngleRad);

        double radius = Math.min(getWidth(), getHeight()) / 3.0;

        final double thickness = 15;
        double xC = getWidth() / 2.0;
        double yC = getHeight() / 2.0;
        double x0 = xC + Math.cos(angleRad) * (radius - thickness);
        double y0 = yC - Math.sin(angleRad) * (radius - thickness);
        double x1 = xC + Math.cos(angleRad) * radius;
        double y1 = yC - Math.sin(angleRad) * radius;

        Shape background0 = new Arc2D.Double(
            xC-radius, yC-radius, 
            radius+radius, radius+radius, 
            Math.toDegrees(minAngleRad), 
            Math.toDegrees(maxAngleRad-minAngleRad), 
            Arc2D.PIE);

        Shape background1 = new Ellipse2D.Double(
            xC-radius+thickness, yC-radius+thickness, 
            radius+radius-thickness-thickness, 
            radius+radius-thickness-thickness);

        Area a = new Area(background0);
        a.subtract(new Area(background1));

        g.setColor(Color.GRAY);
        g.fill(a);
        g.setStroke(new BasicStroke(3.0f, 
            BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g.setColor(Color.LIGHT_GRAY);
        g.draw(a);

        g.setStroke(new BasicStroke(8.0f, 
            BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
        g.setColor(Color.BLACK);
        g.draw(new Line2D.Double(x0, y0, x1, y1));
    }

    private void updateAngle(Point p)
    {
        double xC = getWidth() / 2.0;
        double yC = getHeight() / 2.0;
        double dx = p.getX() - xC;
        double dy = p.getY() - yC;
        double angleRad = Math.atan2(-dy, dx);
        if (angleRad < -Math.PI / 2)
        {
            angleRad = 2 * Math.PI + angleRad;
        }
        angleRad = Math.max(maxAngleRad, Math.min(minAngleRad, angleRad));
        double alpha = (angleRad - minAngleRad) / (maxAngleRad - minAngleRad);
        double value = minValue + alpha * (maxValue - minValue);
        setValue(value);
    }

    @Override
    public void mouseDragged(MouseEvent e)
    {
        updateAngle(e.getPoint());
    }

    @Override
    public void mouseMoved(MouseEvent e)
    {
    }

    @Override
    public void mousePressed(MouseEvent e)
    {
        updateAngle(e.getPoint());
    }

    @Override
    public void mouseClicked(MouseEvent e)
    {
    }

    @Override
    public void mouseReleased(MouseEvent e)
    {
    }

    @Override
    public void mouseEntered(MouseEvent e)
    {
    }

    @Override
    public void mouseExited(MouseEvent e)
    {
    }
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How can I make a jslider actually affect things as it slides?

From Dev

How can I make my border-radius curve outward?

From Dev

How can I make a similar shape to a parallelogram in css?

From Dev

How can I make this type of draw-able shape, android?

From Dev

How can I make a curvy line shape in CSS or Javascript

From Dev

How can I make a curvy line shape in CSS or Javascript

From Dev

How can I make a custom terminal cursor shape?

From Dev

How can I curve a layout?

From Dev

How can I make straight line instead of curve line in d3 force layout?

From Dev

How can I color a curve envelope

From Dev

How can I color a curve envelope

From Dev

How can i create a stair step/curve?

From Dev

How can I find the area above the curve

From Dev

How can I classify a person by identification of shape?

From Dev

How can I add depth to a shape

From Dev

How can I change the shape of a variable in TensorFlow?

From Dev

How can I tell if a shape is combined or not?

From Dev

How can I create this particular shape?

From Dev

How can I shape a webview on Android?

From Dev

How can I draw a shape in CSS?

From Dev

How can I change cursor shape & size?

From Dev

How can I add depth to a shape

From Dev

How can I create this particular shape?

From Dev

How can I change shape color programmatically?

From Dev

how can I change the shape of scroller with JS

From Dev

Can I make this shape as one solid object with css only?

From Dev

Can I make this shape as one solid object with css only?

From Dev

Java how to make a shape(s) that can be draw by clicking button

From Java

How can I curve a line in CSS "roller coaster" animation?

Related Related

HotTag

Archive