Solved

Swing Gui trying to learn How to make a circular slider bar or knob component

Posted on 2006-07-12
8
918 Views
Last Modified: 2013-11-23
I've been trying to find an example of how to make a circular slider bar or round knob(something like a radio volume control), but Haven't been able to find much. I'm a little stuck on how to implement it.
I previously had learned to do a round text field by extending JtextField and overriding the paintComponent
method. I tried to do that with the JSlider, but wasn't even close. It just displays a regular slider bar

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;


public class SliderDemo extends JSlider
{
    public SliderDemo() {  }

      protected void paintComponent(Graphics g)
      {
            Graphics2D g2d = (Graphics2D)g;
              int width = getWidth();
            int height = getHeight();
            g.setColor(getBackground());
            g.fillRoundRect(0, 0, width, height, height, height);
            super.paintComponent(g);
      }

    private static void createAndShowGUI() {
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("SliderDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        SliderDemo roundSlider = new SliderDemo();
        roundSlider.setMajorTickSpacing(10);
      roundSlider.setMinorTickSpacing(1);
      roundSlider.setPaintTicks(true);
      roundSlider.setPaintLabels(true);
        roundSlider.setOpaque(true);
        frame.setContentPane(roundSlider);
        frame.pack();
        frame.setVisible(true);
            }

    public static void main(String[] args) {
               javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}
 An example or link to an example would be great. I want to be able to display the value of the tick mark the knob
is turned to.
0
Comment
Question by:mitchguy
  • 4
  • 3
8 Comments
 
LVL 35

Accepted Solution

by:
girionis earned 125 total points
ID: 17097214
Hi mitchguy

have a look here http://www.dreamfabric.com/java/knob/knob.html

Cheers
0
 
LVL 35

Expert Comment

by:girionis
ID: 17097224
0
 

Author Comment

by:mitchguy
ID: 17098687
The link you provided, is exactly the kind of components I want to try and make. I had found a couple
of those listed on that website prior to posting this question. The problem for me was that I couldn't find any of the source code. I want to make the component myself, all I could find was the component already made for me.
Do you know where an example is in code or can you provide one?
0
 
LVL 35

Expert Comment

by:girionis
ID: 17098873
The first link I posted provides the source code here: http://www.dreamfabric.com/java/knob/dknob_src.zip
0
6 Surprising Benefits of Threat Intelligence

All sorts of threat intelligence is available on the web. Intelligence you can learn from, and use to anticipate and prepare for future attacks.

 

Author Comment

by:mitchguy
ID: 17099612
I was unable to get to the first link, I think it's our firewall. I look forward to
checking it out from home later.
Thanks
0
 
LVL 2

Expert Comment

by:RoyalNepal
ID: 17101084
did u find the code?? if not its here......

/*  
 * DKnob.java
 * (c) 2000 by Joakim Eriksson
 *  
 * DKnob is a component similar to JSlider but with
 * round "user interface", a knob.
 */
package com.dreamfabric;

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.event.*;

public class DKnob extends JComponent
{
    private final static float START = 225;
    private final static float LENGTH = 270;
    private final static float PI = (float) 3.1415;
    private final static float START_ANG = (START/360)*PI*2;
    private final static float LENGTH_ANG = (LENGTH/360)*PI*2;
    private final static float DRAG_RES = (float) 0.01;
    private final static float MULTIP = 180 / PI;
    private final static Color DEFAULT_FOCUS_COLOR = new Color(0x8080ff);

    private int SHADOWX = 1;
    private int SHADOWY = 1;
    private float DRAG_SPEED;
    private float CLICK_SPEED;
    private int size;
    private int middle;
   
    public final static int SIMPLE = 1;
    public final static int ROUND  = 2;
    private int dragType = ROUND;
   

    private final static Dimension MIN_SIZE = new Dimension(40, 40);
    private final static Dimension PREF_SIZE = new Dimension(80, 80);
   
    // Set the antialiasing to get the right look!
    private final static RenderingHints AALIAS =
      new RenderingHints(RenderingHints.KEY_ANTIALIASING,
                     RenderingHints.VALUE_ANTIALIAS_ON);
   
    private ChangeEvent changeEvent = null;
    private EventListenerList listenerList = new EventListenerList();
   
    private Arc2D hitArc = new Arc2D.Float(Arc2D.PIE);
   
    private float ang = (float) START_ANG;
    private float val;
    private int dragpos = -1;
    private float startVal;
    private Color focusColor;
    private double lastAng;
   
    public DKnob() {
      DRAG_SPEED = 0.01F;
      CLICK_SPEED = 0.01F;
      SHADOWX = 1;
      SHADOWY = 1;
      
      focusColor = DEFAULT_FOCUS_COLOR;
      
      setPreferredSize(PREF_SIZE);
      hitArc.setAngleStart(235); // Degrees ??? Radians???
      addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent me) {
                dragpos = me.getX() + me.getY();
                startVal = val;

                // Fix last angle
                int xpos = middle - me.getX();
                int ypos = middle - me.getY();
                lastAng = Math.atan2(xpos, ypos);

                requestFocus();
            }
            
            public void mouseClicked(MouseEvent me) {
                hitArc.setAngleExtent(-(LENGTH + 20));
                if  (hitArc.contains(me.getX(), me.getY())) {         
                  hitArc.setAngleExtent(MULTIP * (ang-START_ANG)-10);
                  if  (hitArc.contains(me.getX(), me.getY())) {
                      decValue();
                  } else incValue();      
                }
            }
          });

      // Let the user control the knob with the mouse
      addMouseMotionListener(new MouseMotionAdapter() {
            public void mouseDragged(MouseEvent me) {
                if ( dragType == SIMPLE) {
                  float f = DRAG_SPEED * (float)
                      ((me.getX() + me.getY()) - dragpos);
                  setValue(startVal + f);
                } else if ( dragType == ROUND) {
                  // Measure relative the middle of the button!
                  int xpos = middle - me.getX();
                  int ypos = middle - me.getY();
                  double ang = Math.atan2(xpos, ypos);
                  double diff = lastAng - ang;
                  setValue((float) (getValue() + (diff / LENGTH_ANG)));

                  lastAng = ang;
                }
            }
            
            public void mouseMoved(MouseEvent me) {
            }
          });

      // Let the user control the knob with the keyboard
      addKeyListener(new KeyListener() {
            
            public void keyTyped(KeyEvent e) {}
            public void keyReleased(KeyEvent e) {}
            public void keyPressed(KeyEvent e) {
                int k = e.getKeyCode();
                if (k == e.VK_RIGHT)
                  incValue();
                else if (k == e.VK_LEFT)
                  decValue();
            }            
          });
      
      // Handle focus so that the knob gets the correct focus highlighting.
      addFocusListener(new FocusListener() {
            public void focusGained(FocusEvent e) {
                repaint();
            }
            public void focusLost(FocusEvent e) {
                repaint();
            }
          });
    }

    public void setDragType(int type) {
      dragType = type;
    }
    public int getDragType() {
      return dragType;
    }
   
    public boolean isManagingFocus() {
      return true;
    }
   
    public boolean isFocusTraversable() {
      return true;
    }
   
   
   
    private void incValue() {
      setValue(val + CLICK_SPEED);
    }
   
    private void decValue() {
      setValue(val - CLICK_SPEED);
    }
   

    public float getValue() {
      return val;
    }

    public void setValue(float val) {
      if (val < 0) val = 0;
      if (val > 1) val = 1;
      this.val = val;
      ang = START_ANG - (float) LENGTH_ANG * val;
      repaint();
      fireChangeEvent();
    }

   
    public void addChangeListener(ChangeListener cl) {
      listenerList.add(ChangeListener.class, cl);
    }
   
    public void removeChangeListener(ChangeListener cl) {
      listenerList.remove(ChangeListener.class, cl);            
    }
   
    public Dimension getMinimumSize() {
      return MIN_SIZE;
    }
   
    protected void fireChangeEvent() {
      // Guaranteed to return a non-null array
      Object[] listeners = listenerList.getListenerList();
      // Process the listeners last to first, notifying
      // those that are interested in this event
      for (int i = listeners.length-2; i>=0; i-=2) {
          if (listeners[i] == ChangeListener.class) {
            // Lazily create the event:
            if (changeEvent == null)
                changeEvent = new ChangeEvent(this);
            ((ChangeListener)listeners[i+1]).stateChanged(changeEvent);
          }
      }
    }
 

    // Paint the DKnob
    public void paint(Graphics g) {
      int width = getWidth();
      int height = getHeight();
      size = Math.min(width, height) - 22;
      middle = 10 + size/2;

      if (g instanceof Graphics2D) {
          Graphics2D g2d = (Graphics2D) g;
          g2d.setBackground(getParent().getBackground());
          g2d.addRenderingHints(AALIAS);
          
          // For the size of the "mouse click" area
          hitArc.setFrame(4, 4, size+12, size+12);
      }
      
      // Paint the "markers"
      for (float a2 = START_ANG; a2 >= START_ANG - LENGTH_ANG; a2=a2 -(float)
             (LENGTH_ANG/10.01))
          {
            int x = 10 + size/2 + (int)((6+size/2) * Math.cos(a2));
            int y = 10 + size/2 - (int)((6+size/2) * Math.sin(a2));
            g.drawLine(10 + size/2, 10 + size/2, x, y);
            
          }
      
      // Set the position of the Zero
      g.drawString("0", 2, size + 10);
      
      // Paint focus if in focus
      if (hasFocus()) {
          g.setColor(focusColor);
      } else {
          g.setColor(Color.white);
      }

      g.fillOval(10, 10, size, size);
      g.setColor(Color.gray);
      g.fillOval(14 + SHADOWX, 14 + SHADOWY, size-8, size-8);
      
      g.setColor(Color.black);
      g.drawArc(10, 10, size, size, 315, 270);
      g.fillOval(14, 14, size-8, size-8);
      g.setColor(Color.white);
      
      int x = 10 + size/2 + (int)(size/2 * Math.cos(ang));
      int y = 10 + size/2 - (int)(size/2 * Math.sin(ang));
      g.drawLine(10 + size/2, 10 + size/2, x, y);
      g.setColor(Color.gray);
      int s2 = (int) Math.max(size / 6, 6);
      g.drawOval(10 + s2, 10 + s2, size - s2*2, size - s2*2);
      
      int dx = (int)(2 * Math.sin(ang));
      int dy = (int)(2 * Math.cos(ang));
      g.drawLine(10 + dx + size/2, 10 + dy + size/2, x, y);
      g.drawLine(10-dx + size/2, 10-dy + size/2, x, y);
    }
}





package com.dreamfabric;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import javax.swing.event.*;

public class DTest
{
      public static void main(String[] args)
      {
          JFrame win = new JFrame("DTest!");
          win.getContentPane().setLayout(new BorderLayout());
          win.setSize(120,140);

          JPanel panel = new JPanel(new BorderLayout());
          panel.setBackground(new Color(200,200,255));
          win.getContentPane().add(panel, BorderLayout.CENTER);

          DKnob ts;
          JLabel jl;
          ChangeListener cl;
          panel.add(ts = new DKnob(), BorderLayout.CENTER);
          panel.add(jl = new JLabel("Volume: 0"), BorderLayout.NORTH);
          ts.setValue((float)1.0);
          final JLabel jla = jl;
          ts.addChangeListener(new ChangeListener() {
                public void stateChanged(ChangeEvent e) {
                  DKnob t = (DKnob) e.getSource();
                  int vol;
                  jla.setText("Volume: " + (vol = (int)(15 * t.getValue())));
                }
            });
          win.show();
      }
}


0
 

Author Comment

by:mitchguy
ID: 17112438
yes I found the code. Thanks
0
 
LVL 35

Expert Comment

by:girionis
ID: 17114102
:)
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Update (December 2011): Since this article was published, the things have changed for good for Android native developers. The Sequoyah Project (http://www.eclipse.org/sequoyah/) automates most of the tasks discussed in this article. You can even fin…
Introduction This article is the second of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article covers the basic installation and configuration of the test automation tools used by…
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

758 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now