график x-y и вращающийся текст метки оси

Приведенный ниже код отображает некоторые простые данные 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);
    }
}

person CodeMed    schedule 20.12.2011    source источник
comment
+1 для sscce.   -  person trashgod    schedule 20.12.2011


Ответы (2)


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

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

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

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

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

Установите поворот объекта Graphics, отрисовывайте текст, затем верните поворот объекта Graphics обратно на 0.

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

person camickr    schedule 20.12.2011

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

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

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

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

person trashgod    schedule 20.12.2011
comment
+1 за попытку помочь. Я не использую JFreeChart по причинам лицензирования. Но я прочитал статьи, которые вы прислали. Спасибо. - person CodeMed; 20.12.2011