2017-09-30 36 views
0

所以我想創建一個數字線類,我可以使用它來沿單個軸顯示單個點,但我希望它能夠響應當前所在容器的大小,並相應地改變它的大小。不幸的是,我無法正確使用getWidth()和getHeight()來獲取我想要的數字。這是迄今爲止我所編寫的代碼:使用數字線在Java中顯示一個點,getWidth()和getHeight()不能正確校準位置

import javax.swing.*; 
import java.awt.*; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Line2D; 

public class NumberLine extends JPanel { 
    private int value; 
    private Color green1 = new Color(32, 77, 2); 

@Override 
public void paintComponent(Graphics g) 
{ 
    Graphics2D g2 = (Graphics2D) g; 
    int maxXValue = getWidth(); 
    int maxYValue = getHeight(); 
    Line2D.Float xline = new Line2D.Float((float) maxXValue/6, (float) maxYValue/2, (float) maxXValue * (5/6), (float) maxYValue/2); 
    Line2D.Float yline = new Line2D.Float((float) maxXValue/ 2, (float) maxYValue * (9/20), (float) maxXValue/2, (float) maxYValue *(11/20)); 
    g2.draw(xline); 
    g2.draw(yline); 
    Ellipse2D.Float cir = new Ellipse2D.Float((float) (maxXValue/10 + (8 * value/1000) * (maxXValue)), (float) (maxYValue/2), 10F, 10F); 
    g2.setColor(green1); 
    g2.fill(cir); 
} 


public NumberLine(int val0) { 
    value = val0; 
} 

public static void main(String[] args) { 
    JFrame frame = new JFrame(); 
    frame.setSize(150,100); 
    NumberLine num = new NumberLine(5); 
    frame.setContentPane(num); 
    frame.setVisible(true); 

} 
} 

理想情況下,我想的東西,例如,如果我是做

NumberLine num = new NumberLine(5); 

我會得到的東西看起來像:

-*------------------

取而代之,我得到:

Output from the code I have written

+0

請參閱編輯回答 –

回答

2

我認爲你的問題是一個基本的幾何。如果您嘗試將圓圈居中,則需要從其位置減去其寬度和高度的一半。就是這樣:

Ellipse2D.Float cir = new Ellipse2D.Float(
     (float) (maxXValue/10 + (8 * value/1000) * (maxXValue)) - 5, 
     (float) (maxYValue/2) - 5, 10F, 10F); 

而且你正在做的INT除法和正在返回0值,你不希望他們。更改

Line2D.Float yline = new Line2D.Float((float) maxXValue/2, (float) maxYValue * (9/20), 
     (float) maxXValue/2, (float) maxYValue * (11/20)); 

Line2D.Float yline = new Line2D.Float((float) maxXValue/2, (float) maxYValue * (9f/20f), 
     (float) maxXValue/2f, (float) maxYValue * (11f/20f)); 

無關的問題:

  • 不要忘記調用父類的的paintComponent方法:

    @Override 
    public void paintComponent(Graphics g) { 
        super.paintComponent(g); // !! don't forget this! 
    
  • ,避免 「魔」號碼在你的p他們調試一個熊時的程式。

  • 使用的RenderingHints理順你的Graphics2D繪圖:

    // rendering hints to smooth out your drawing 
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
        RenderingHints.VALUE_ANTIALIAS_ON); 
    
  • 在美國東部時間啓動Swing GUI的:

    SwingUtilities.invokeLater(() -> { 
        JFrame frame = new JFrame(); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    

例如,像:

import java.awt.BasicStroke; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.Stroke; 
import javax.swing.JPanel; 

public @SuppressWarnings("serial") 
class NumberLine3 extends JPanel { 
    private static final double X_GAP = 1.0/20.0; 
    private static final double MAJOR_TIC_HT = 0.4; 
    private static final int PREF_W = 600; 
    private static final int PREF_H = 50; 
    private static final Stroke MAIN_STROKE = new BasicStroke(5f); 
    private static final Stroke MAJOR_TIC_STOKE = new BasicStroke(3f); 
    private static final int CIRCLE_WIDTH = 20; 
    private static final Color VALUE_COLOR = new Color(32, 230, 2); 
    private int maxX; 
    private int majorTickCount; 
    private int minorTicksPerMajor; 
    private double value; 

    public NumberLine3(int maxX, int majorTickCount, int minorTicksPerMajor, double value) { 
     this.maxX = maxX; 
     this.majorTickCount = majorTickCount; 
     this.minorTicksPerMajor = minorTicksPerMajor; 
     this.value = value; 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     super.paintComponent(g); 
     Graphics2D g2 = (Graphics2D) g; 

     // rendering hints to smooth out your drawing 
     g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 

     Graphics2D g2b = (Graphics2D) g2.create(); // so we can change stroke without problems 
     g2b.setStroke(MAIN_STROKE); 
     int x1 = (int) xValueToScreen(-maxX); 
     int y1 = getHeight()/2; 
     int x2 = (int) xValueToScreen(maxX); 
     int y2 = y1; 
     g2b.drawLine(x1, y1, x2, y2); 
     g2b.setStroke(MAJOR_TIC_STOKE); 
     for (int i = 0; i <= 2 * majorTickCount; i++) { 
      double xVal = ((double) i * maxX)/majorTickCount - maxX; 
      x1 = (int) xValueToScreen(xVal); 
      x2 = x1; 
      double dY1 = getHeight() * (1 - MAJOR_TIC_HT)/2.0; 
      if (i == majorTickCount) { 
       dY1 = 0.5 * dY1; 
      } 
      double dY2 = getHeight() - dY1; 
      g2b.drawLine(x1, (int) dY1, x2, (int) dY2); 
     } 
     g2b.dispose(); 

     g2.setColor(VALUE_COLOR); 
     x1 = (int) (xValueToScreen(value) - CIRCLE_WIDTH/2.0); 
     y1 = (int) (getHeight() - CIRCLE_WIDTH)/2; 
     g2.fillOval(x1, y1, CIRCLE_WIDTH, CIRCLE_WIDTH); 
    } 

    private double xValueToScreen(double xValue) { 
     double gap = getWidth() * X_GAP; 
     double scale = (double) (getWidth() - 2 * gap)/(2 * maxX); 
     return (xValue + maxX) * scale + gap; 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     if (isPreferredSizeSet()) { 
      return super.getPreferredSize(); 
     } 
     return new Dimension(PREF_W, PREF_H); 
    } 

    public double getValue() { 
     return value; 
    } 

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

    public int getMaxX() { 
     return maxX; 
    } 

    public int getMajorTickCount() { 
     return majorTickCount; 
    } 

    public int getMinorTicksPerMajor() { 
     return minorTicksPerMajor; 
    } 
} 

可以測試的有:

import java.awt.BorderLayout; 
import javax.swing.BorderFactory; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JSlider; 
import javax.swing.SwingUtilities; 

@SuppressWarnings("serial") 
public class NumberLine3Test extends JPanel { 
    private static final int MAX_X = 40; 
    private static final int MAJOR_TICS = 4; 
    private static final int MINOR_TICS = 5; 
    private double value = 0.0; 
    private NumberLine3 numberLine3 = new NumberLine3(MAX_X, MAJOR_TICS, MINOR_TICS, value); 
    private JSlider slider = new JSlider(-MAX_X, MAX_X, 0); 

    public NumberLine3Test() { 
     slider.setPaintTicks(true); 
     slider.setMajorTickSpacing(10); 
     slider.setMinorTickSpacing(5); 
     slider.addChangeListener(ce -> { 
      value = slider.getValue(); 
      numberLine3.setValue(value); 
     }); 

     JPanel sliderPanel = new JPanel(); 
     sliderPanel.add(slider); 
     int ebGap = 40; 
     sliderPanel.setBorder(BorderFactory.createEmptyBorder(ebGap, ebGap, ebGap, ebGap)); 

     setLayout(new BorderLayout()); 
     add(numberLine3, BorderLayout.PAGE_START); 
     add(sliderPanel); 
    } 

    private static void createAndShowGui() { 
     NumberLine3Test mainPanel = new NumberLine3Test(); 

     JFrame frame = new JFrame("NumberLine3"); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.getContentPane().add(mainPanel); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(() -> createAndShowGui()); 
    } 
} 
+0

感謝您的回答。問題不在於圓的位置,而在於線的位置。我希望中間的水平線不在左邊,因爲我現在畫的垂直線甚至不在屏幕上。我還有一些關於你的其他問題的問題,什麼是美國東部時間?而且,什麼是幻數?雖然不要太擔心這些神奇的數字,但這聽起來像是我可以輕鬆搜索的東西。 – JenniferHL3

+0

// @ JenniferHL3:啊,我的不好。請顯示一個更好的ASCII圖像或*真實*圖像,你正在努力完成的。 –

+0

@ JenniferHL3:EDT = Event Dispatch Thread。主要的Swing線程負責關鍵的Swing動作,包括繪製和與用戶交互。有關更多信息,請參見:[課程:Swing中的併發](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/)。 –

相關問題