JSlider 刻度消失

问题描述 投票:0回答:2
public class Main {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame frame = new JFrame("Slider Example");

            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 100, 50);
            slider.setUI(new BasicSliderUI() {
                
                @Override
                public void paint(Graphics g, JComponent c) {
                    super.paint(g, c);
                }
                
                @Override
                public void paintTrack(Graphics g) {
                    if(slider.getOrientation() == JSlider.HORIZONTAL) {
                        int y = (trackRect.height / 2) - 2;
                        int w = trackRect.width;

                        g.translate(trackRect.x, trackRect.y + y);

                        g.setColor(Color.white);
                        
                        g.drawLine(0, -3, 0, 3);
                        g.drawLine(w -1, -3, w -1, 3);
                        
                        g.drawLine(0, 0, w -2, 0); // Main Line

                        g.translate(-trackRect.x, -(trackRect.y + y));
                    }
                }
                
                @Override
                public void paintThumb(Graphics g1) {
                    Rectangle knobBounds = thumbRect;
                    int x = knobBounds.x;
                    int y = knobBounds.y;
                    int w = knobBounds.width;
                    int h = knobBounds.height;

                    Graphics2D g = (Graphics2D) g1;
                    
                    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    g.setColor(Color.white);
                    g.translate(x, y);
                    
                    g.fillOval(0, 3, w, w);
                }
                
                @Override
                protected void paintMajorTickForHorizSlider(Graphics g, Rectangle tickBounds, int x) {
                    g.setColor(Color.white);
                    g.drawLine(x, -5, x, tickBounds.height / 2 - 5);
                }
                
                @Override
                protected void paintMinorTickForHorizSlider(Graphics g, Rectangle tickBounds, int x) {
                    g.setColor(Color.white);
                    g.drawLine(x, -5, x, tickBounds.height / 2 - 10);
                }
            });
            slider.setMajorTickSpacing(10);
            slider.setMinorTickSpacing(5);
            slider.setPaintTicks(true);
            slider.setPaintLabels(true);

            frame.getContentPane().add(slider);
            slider.setBackground(Color.black);
            frame.getContentPane().setBackground(Color.black);
            frame.setSize(400, 150);
            frame.setVisible(true);
        });
    }
}

我在代码片段中遇到了一个奇怪的行为,我为我的 UI 定制了 JSlider。令人费解的是,当我拖动滑块拇指时,刻度线神秘地消失了。然而,一旦我松开拇指,它们就会神奇地重新出现。有人可以帮助我解决这里可能发生的事情吗?我一直在寻找解决方案,但找不到来源。

java swing jslider
2个回答
0
投票

还是找不到问题的根源,但是在

super.paint()
之前画勾就解决了问题。

public void paint(Graphics g1, JComponent c) {
    paintTicks(g1);
    super.paint(g1, c);
}

0
投票

在正常的

JSlider
中,刻度不会因鼠标拖动而改变,因此
tickRect
不会执行重画,如下所示。

// BasicSliderUI
public void paint( Graphics g, JComponent c ) {
  //...
  if ( slider.getPaintTicks() && clip.intersects( tickRect ) ) {
    paintTicks( g ); }
  }

建议覆盖

TrackListener#mouseDragged(...)
,以便在鼠标拖动时重绘整个
JSlider

class CustomSliderUI extends BasicSliderUI {
  @Override
  protected void paintMajorTickForHorizSlider(Graphics g, Rectangle tickBounds, int x) {
    // ...
  }

  @Override
  protected void paintMinorTickForHorizSlider(Graphics g, Rectangle tickBounds, int x) {
    // ...
  }

  @Override
  protected BasicSliderUI.TrackListener createTrackListener(JSlider slider) {
    return new TrackListener() {
      @Override
      public void mouseDragged(MouseEvent e) {
        super.mouseDragged(e);
        e.getComponent().repaint();
      }
    };
  }
}

Main2.java

import java.awt.*;
import java.awt.event.MouseEvent;
import javax.swing.*;
import javax.swing.plaf.basic.BasicSliderUI;

public class Main2 {
  public Component makeUI() {
    JSlider slider2 = new JSlider(JSlider.HORIZONTAL, 0, 100, 50) {
      @Override public void updateUI() {
        super.updateUI();
        setUI(new CustomSliderUI());
      }
    };
    slider2.setMajorTickSpacing(10);
    slider2.setMinorTickSpacing(5);
    slider2.setPaintTicks(true);
    slider2.setPaintLabels(true);
    slider2.setBackground(Color.BLACK);

    JPanel p = new JPanel(new BorderLayout());
    p.setBackground(Color.BLACK);
    p.add(slider2);
    return p;
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame("Slider Example");
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new Main2().makeUI());
      f.setSize(400, 150);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

class CustomSliderUI extends BasicSliderUI {
  @Override
  public void paintTrack(Graphics g) {
    if (slider.getOrientation() == JSlider.HORIZONTAL) {
      int y = (trackRect.height / 2) - 2;
      int w = trackRect.width;
      g.translate(trackRect.x, trackRect.y + y);
      g.setColor(Color.white);
      g.drawLine(0, -3, 0, 3);
      g.drawLine(w - 1, -3, w - 1, 3);
      g.drawLine(0, 0, w - 2, 0); // Main Line
      g.translate(-trackRect.x, -(trackRect.y + y));
    }
  }

  @Override
  public void paintThumb(Graphics g1) {
    Rectangle knobBounds = thumbRect;
    int x = knobBounds.x;
    int y = knobBounds.y;
    int w = knobBounds.width;
    int h = knobBounds.height;
    Graphics2D g = (Graphics2D) g1;
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    g.setColor(Color.white);
    g.translate(x, y);
    g.fillOval(0, 3, w, w);
  }

  @Override
  protected void paintMajorTickForHorizSlider(Graphics g, Rectangle tickBounds, int x) {
    g.setColor(Color.white);
    g.drawLine(x, -5, x, tickBounds.height / 2 - 5);
  }

  @Override
  protected void paintMinorTickForHorizSlider(Graphics g, Rectangle tickBounds, int x) {
    g.setColor(Color.white);
    g.drawLine(x, -5, x, tickBounds.height / 2 - 10);
  }

  @Override
  protected BasicSliderUI.TrackListener createTrackListener(JSlider slider) {
    return new TrackListener() {
      @Override
      public void mouseDragged(MouseEvent e) {
        super.mouseDragged(e);
        e.getComponent().repaint();
      }
    };
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.