график xy и вращающийся текст оси-метки - PullRequest
3 голосов
/ 20 декабря 2011

Приведенный ниже код отображает некоторые простые данные x-y, но у него есть две проблемы, которые я не знаю, как исправить.

Во-первых, он отображает отрицательные значения для некоторых точек данных, что означает линии, продолжающиеся к югу ниже оси X. Поскольку точки данных выбираются случайным образом, возможно, вам придется немного изменить размер кадра, чтобы просмотреть новые случайные числа, которые будут нанесены таким образом, чтобы показать эту ошибку. Все значения данных будут положительными, поэтому я хочу, чтобы все отклонения проецировались на север выше синей нижней линии маркера, и мне нужно убедиться, что отклонения не распространяются на юг ниже синей нижней линии маркера.

Во-вторых, метка оси Y занимает слишком много места на экране. Его нужно повернуть на -90 градусов. Однако все примеры, которые я видел для этого, включают вращение всей панели с помощью объекта graphics2d. Я не хочу вращать всю панель. Вместо этого я просто хочу повернуть текст метки оси Y.

Может кто-нибудь показать мне, как изменить код ниже, чтобы исправить эти две конкретные проблемы?

Код находится в следующих двух файлах:

GUI.java

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

class GUI{

GUI() { 
    // Create a new JFrame container. 
    JFrame jfrm = new JFrame("X-Y Plot"); 
    // Specify FlowLayout for the layout manager. 
    jfrm.getContentPane().setLayout(new FlowLayout()); 
    int frameHeight = 400;
    int frameWidth = 300;
    // Give the frame an initial size. 
    jfrm.setSize(frameWidth, frameHeight);

    // Terminate the program when the user closes the application. 
    jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    // Create a text-based label.
    JVertLabel myVLabel = new JVertLabel("y-axis label");
    int width = myVLabel.WIDTH;

    PaintPanel myPP = new PaintPanel(frameWidth-width-50-20,frameHeight-70);
    jfrm.add(myPP);

    jfrm.add(myVLabel);// Add the label to the frame.

    // Display the frame. 
    jfrm.setVisible(true); 
} 

public static void main(String args[]) { 
    // Create the frame on the event dispatching thread.
    SwingUtilities.invokeLater(new Runnable() {public void run(){new GUI();}});
}

    public class JVertLabel extends JComponent {

        private String text;

        public JVertLabel(String s) {
            text = s;
        }//constructor

        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.rotate(Math.toRadians(-90));
            g2d.drawString(text, 0, 0);
        }
    }
}

PaintPanel.java

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

class PaintPanel extends JPanel {

    Insets ins; // holds the panel's insets 
    Random rand; // used to generate random numbers 

    PaintPanel(int w, int h) {
        setOpaque(true);// Ensure that panel is opaque.
        setPreferredSize(new Dimension(w, h));// Set preferred dimension as specfied. 
        rand = new Random();
    }

    protected void paintComponent(Graphics g) {// Override paintComponent() method.
        super.paintComponent(g);// Always call superclass method first.
        int height = getHeight();// Get height of component.
        int width = getWidth();// Get width of component.
        ins = getInsets();// Get the insets.
        // Get dimensions of text
        Graphics2D g2d = (Graphics2D) g;
        Font font = new Font("Serif", Font.PLAIN, 12);
        FontMetrics fontMetrics = g2d.getFontMetrics();
        String xString = ("x-axis label");
        int xStrWidth = fontMetrics.stringWidth(xString);
        int xStrHeight = fontMetrics.getHeight();
        String yString = "y-axis-label";
        int yStrWidth = fontMetrics.stringWidth(yString);
        int yStrHeight = fontMetrics.getHeight();
        int leftStartPlotWindow = ins.left + 5 + yStrWidth;
        int hPad = 3;

        // Fill panel by plotting random data in a bar graph. 
        for (int i = leftStartPlotWindow + hPad; i <= width - leftStartPlotWindow - hPad + yStrWidth + 1; i += 4) {
            int h = Math.abs(rand.nextInt(height - ins.bottom));//Get rand# betw/0 and max height of drawing area.
            // If generated value w/in or too close to border, change it to just outside border.
            if (h <= ins.top) {
                h = ins.top + 1;
            }
            g.drawLine(i, Math.abs(height - ins.bottom - xStrHeight - 5), i, h);// Draw a line that represents data.
        }
        g.setColor(Color.blue);
        g.drawRect(leftStartPlotWindow, ins.bottom + 2, width - leftStartPlotWindow - ins.right - hPad, height - xStrHeight - 6);
        g.setColor(Color.red);
        g.drawRect(ins.left, ins.bottom, width - ins.left - 1, height - ins.bottom - 1);
        g.drawString(xString, (width / 2) - (xStrWidth / 2), height - ins.bottom - 6);
        g.drawString(yString, ins.left, height / 2);
    }
}

Ответы [ 2 ]

3 голосов
/ 20 декабря 2011

Все значения данных будут положительными, поэтому я хочу, чтобы все отклонения проецировались на север выше синей нижней линии маркера, и мне нужно убедиться, что отклонения не распространяются на юг ниже синей нижней линии маркера.

Вам необходимо вычислить случайную высоту, чтобы все значения вписывались в доступное пространство. Так что расчет будет что-то вроде:

int randomHeight = panelHeight - offset.top - offset.bottom - heightForTheXAxisText;

Тогда вам не нужно беспокоиться об отрицательных значениях или верхней части линии, выходящей за границы панели.

все примеры, которые я видел для этого, включают вращение всей панели с использованием объекта graphics2d. Я не хочу вращать всю панель. Вместо этого я просто хочу повернуть текст метки оси Y.

Установите вращение графического объекта, нарисуйте текст, затем верните вращение графического объекта обратно в 0.

Или вы создаете новый объект Graphcis из текущего объекта Graphics, затем применяете вращение, рисуете текст и затем удаляете временный объект Graphics.

2 голосов
/ 20 декабря 2011

JFreeChart решает обе проблемы по умолчанию, как показано в этом примере .

В вашем примере

  1. Вам придется создать модель данных, прежде чем пытаться ее визуализировать.Затем вы можете отсканировать его для значений min и max , чтобы определить пределы вашей оси range .List<Double> может быть подходящим выбором.

  2. Вы можете повернуть метку диапазона, изменив графический контекст AffineTransform, как показано в RotateText.

...