本文介绍了Java Swing - 重绘()无法正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我从开始学习计划。我尝试以实时模式编辑点。我将MouseMotionListener添加到构造函数中,然后编写一些基本函数以获取指向鼠标的点并编辑此点。当我在构造函数中得到(x,y)点时, repaint()很奇怪。当我得到(x,y)点在 paintComponent 时, repaint()根本不起作用。所以,这是在构造函数中获取(x,y)的图像,并且在 paintComponent 中。我的错误在哪里?

  package simplegrapher2; 

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import static java.lang.Math.sqrt;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
导入javax.swing.SwingUtilities;

public class SimpleGrapher2 extends JPanel {

private int width = 800;
private int heigth = 400;
private int padding = 25;
private int labelPadding = 25;
private color lineColor = new Color(44,102,230,180);
private color pointColor = new Color(100,100,100,180);
private color gridColor = new Color(200,200,200,200);
private static final Stroke GRAPH_STROKE = new BasicStroke(2f);
private int pointWidth = 4;
private int numberYDivisions = 10;
私人列表< Double>分数;
private static double serieX = 0;
public List< Point2D.Double> graphPoints;

public SimpleGrapher2(列表< Double>分数){
this.scores = scores;
addMouseMotionListener(new MouseMotionListener(){
@Override
public void mouseDragged(MouseEvent me){
double x = me.getX();
double y = me .getY();
findNearPoint(x,y);
editSerie(x,y);
revalidate();
repaint();
}

@Override
public void mouseMoved(MouseEvent me){}
});

double xScale =((double)getWidth() - (2 * padding) - labelPadding)/(scores.size() - 1);
double yScale =((double)getHeight() - 2 * padding - labelPadding)/(getMaxScore() - getMinScore());

graphPoints = new ArrayList<>();
for(int i = 0; i< scores.size(); i ++){
double x1 =(double)(i * xScale + padding + labelPadding);
double y1 =(double)((getMaxScore() - scores.get(i))* yScale + padding);
graphPoints.add(new Point2D.Double(x1,y1));
}
}

@Override
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 =(Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

/ * double xScale =((double)getWidth() - (2 * padding) - labelPadding)/(scores.size() - 1);
double yScale =((double)getHeight() - 2 * padding - labelPadding)/(getMaxScore() - getMinScore());

graphPoints = new ArrayList<>();
for(int i = 0; i< scores.size(); i ++){
double x1 =(double)(i * xScale + padding + labelPadding);
double y1 =(double)((getMaxScore() - scores.get(i))* yScale + padding);
graphPoints.add(new Point2D.Double(x1,y1));
} * /

//绘制白色背景
g2.setColor(Color.WHITE);
g2.fillRect(padding + labelPadding,padding,getWidth() - (2 * padding) - labelPadding,getHeight() - 2 * padding - labelPadding);
g2.setColor(Color.BLACK);

//为y轴创建孵化标记和网格线。
for(int i = 0; i< numberYDivisions + 1; i ++){
int x0 = padding + labelPadding;
int x1 = pointWidth + padding + labelPadding;
int y0 = getHeight() - ((i *(getHeight() - padding * 2 - labelPadding))/ numberYDivisions + padding + labelPadding);
int y1 = y0;
if(scores.size()> 0){
g2.setColor(gridColor);
g2.drawLine(padding + labelPadding + 1 + pointWidth,y0,getWidth() - padding,y1);
g2.setColor(Color.BLACK);
String yLabel =((int)((getMinScore()+(getMaxScore() - getMinScore())*((i * 1.0)/ numberYDivisions))* 100))/ 100.0 +;
FontMetrics指标= g2.getFontMetrics();
int labelWidth = metrics.stringWidth(yLabel);
g2.drawString(yLabel,x0 - labelWidth - 5,y0 +(metrics.getHeight()/ 2) - 3);
}
g2.drawLine(x0,y0,x1,y1);
}

//和x轴
(int i = 0; i< scores.size(); i ++){
if(scores) size()> 1){
int x0 = i *(getWidth() - padding * 2 - labelPadding)/(scores.size() - 1)+ padding + labelPadding;
int x1 = x0;
int y0 = getHeight() - padding - labelPadding;
int y1 = y0 - pointWidth;
if((i%((int)((scores.size()/ 20.0))+ 1))== 0){
g2.setColor(gridColor);
g2.drawLine(x0,getHeight() - padding - labelPadding - 1 - pointWidth,x1,padding);
g2.setColor(Color.BLACK);
String xLabel = i +;
FontMetrics指标= g2.getFontMetrics();
int labelWidth = metrics.stringWidth(xLabel);
g2.drawString(xLabel,x0 - labelWidth / 2,y0 + metrics.getHeight()+ 3);
}
g2.drawLine(x0,y0,x1,y1);



//创建x和y轴
g2.drawLine(padding + labelPadding,getHeight() - padding - labelPadding,padding + labelPadding,padding );
g2.drawLine(padding + labelPadding,getHeight() - padding - labelPadding,getWidth() - padding,getHeight() - padding - labelPadding);

笔划oldStroke = g2.getStroke();
g2.setColor(lineColor);
g2.setStroke(GRAPH_STROKE);
for(int i = 0; i< graphPoints.size() - 1; i ++){
double x1 = graphPoints.get(i).x;
double y1 = graphPoints.get(i).y;
double x2 = graphPoints.get(i + 1).x;
double y2 = graphPoints.get(i + 1).y;
g2.draw(new Line2D.Double(x1,y1,x2,y2));
}

g2.setStroke(oldStroke);
g2.setColor(pointColor);
for(int i = 0; i< graphPoints.size(); i ++){
double x = graphPoints.get(i).x - pointWidth / 2;
double y = graphPoints.get(i).y - pointWidth / 2;
int ovalW = pointWidth;
int ovalH = pointWidth;
//g2.fillOval(x,y,ovalW,ovalH);



public void findNearPoint(double x,double y){
double delta = 0;
for(int j = 0; j< graphPoints.size(); j ++){
double sx = graphPoints.get(j).x;
double sy = graphPoints.get(j).y;
double root = sqrt((x-sx)*(x-sx)+(y-sy)*(y-sy));
if(j == 0){
delta = root;
serieX = sx;
}
else if(root< delta){
serieX = sx;
delta = root;



$ b public void editSerie(double x,double y){
double tmpSerieX = serieX;
int ind = 0;
for(int i = 0; i< graphPoints.size(); i ++){
if(graphPoints.get(i).x == tmpSerieX){
ind = i;
}
}
graphPoints.remove(ind);
graphPoints.add(ind,new Point2D.Double(x,y));
serieX = x;
}

private double getMinScore(){
double minScore = Double.MAX_VALUE; (双分:分数)
{
minScore = Math.min(minScore,分数);
}
返回minScore;
}

private double getMaxScore(){
double maxScore = Double.MIN_VALUE;
for(Double score:分数){
maxScore = Math.max(maxScore,分数);
}
返回maxScore;
}

public void setScores(List< Double> scores){
this.scores = scores;
invalidate();
this.repaint();
}

公共列表< Double> getScores(){
返回分数;
}

private static void createAndShowGui(){
List< Double> scores = new ArrayList<>();
Random random = new Random();
int maxDataPoints = 40;
int maxScore = 10; (int i = 0; i scores.add((double)random.nextDouble()* maxScore)的
;
}
SimpleGrapher2 mainPanel = new SimpleGrapher2(scores);
mainPanel.setPreferredSize(new Dimension(800,600));
JFrame frame = new JFrame(DrawGraph);
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(new Runnable(){
public void run(){
createAndShowGui();
}
});
}
}


x / yScale 时, c code $ ...
$ b $ pre $ public SimpleGrapher2(List< Double> scores){
// ...
double xScale =((double)getWidth() - (2 * padding) - labelPadding)/(scores.size() - 1);
double yScale =((double)getHeight() - 2 * padding - labelPadding)/(getMaxScore() - getMinScore());
// ...
}

在构建组件的时候,组件大小为 0x0 。您需要等到组件在计算点之前以某种有意义的方式调整大小...



这也是有问题的,因为组件可能会重新调整大小,它在第一次在屏幕上实现。



过去我所做的是使用Swing Timer

code>设置为一个小小的延迟,以允许在小时间范围内调整组件大小。一旦完全解决, Timer 将会触发,您可以执行所需的操作,例如...

 public SimpleGrapher2(List< Double> scores){
// ...
addComponentListener(new ComponentAdapter(){
$ b $ private Timer initTimer = new Timer(200,new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
initTimer.stop();
double xScale =((double )getWidth() - (2 * padding) - labelPadding)/(scores.size() - 1);
double yScale =((double)getHeight() - 2 * padding - labelPadding)/(getMaxScore() - getMinScore());

graphPoints = new ArrayList<>();
for(int i = 0; i< scores.size(); i ++){
double x1 =(double)(i * xScale + padding + labelPadding);
double y1 =(double)((getMaxScore() - scores.get(i))* yScale + padding);
graphPoints.add(new Point2D.Double(x1,y1));
}
repaint();
}
});
$ b $ @Override
public void componentResized(ComponentEvent e){
if(graphPoints == null){
initTimer.restart();
}
}

});






$ b

所有这些都会等到定时器 compoentResized 事件超过200毫秒(你可以使用这个值来使它更接近你想要的,但我发现大约250毫秒是一个合理的延迟) p>

您需要更正 paintComponent 以允许 graphPoints 一直是 null


I take program from this topic. I try to edit points in real-time mode. I add MouseMotionListener to the constructor and write some basic functions to get near point to mouse and edit this point. When I get (x,y) points in the constructor, repaint() works strange. When I get (x,y) points in paintComponent, repaint() doesn't work at all. So, this are images with getting (x,y) in the constructor and in paintComponent. Where is my mistake?

package simplegrapher2;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Stroke;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import static java.lang.Math.sqrt;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class SimpleGrapher2 extends JPanel {

    private int width = 800;
    private int heigth = 400;
    private int padding = 25;
    private int labelPadding = 25;
    private Color lineColor = new Color(44, 102, 230, 180);
    private Color pointColor = new Color(100, 100, 100, 180);
    private Color gridColor = new Color(200, 200, 200, 200);
    private static final Stroke GRAPH_STROKE = new BasicStroke(2f);
    private int pointWidth = 4;
    private int numberYDivisions = 10;
    private List<Double> scores;
    private static double serieX = 0;
    public List<Point2D.Double> graphPoints;

    public SimpleGrapher2(List<Double> scores) {
        this.scores = scores;
        addMouseMotionListener(new MouseMotionListener() {
            @Override
            public void mouseDragged(MouseEvent me) {
                double x = me.getX();
                double y = me.getY();
                findNearPoint(x, y);
                editSerie(x, y);
                revalidate();
                repaint();
            }

            @Override
            public void mouseMoved(MouseEvent me) {}
        });

        double xScale = ((double) getWidth() - (2 * padding) - labelPadding) / (scores.size() - 1);
        double yScale = ((double) getHeight() - 2 * padding - labelPadding) / (getMaxScore() - getMinScore());

        graphPoints = new ArrayList<>();
        for (int i = 0; i < scores.size(); i++) {
            double x1 = (double) (i * xScale + padding + labelPadding);
            double y1 = (double) ((getMaxScore() - scores.get(i)) * yScale + padding);
            graphPoints.add(new Point2D.Double(x1, y1));
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

        /*double xScale = ((double) getWidth() - (2 * padding) - labelPadding) / (scores.size() - 1);
        double yScale = ((double) getHeight() - 2 * padding - labelPadding) / (getMaxScore() - getMinScore());

        graphPoints = new ArrayList<>();
        for (int i = 0; i < scores.size(); i++) {
            double x1 = (double) (i * xScale + padding + labelPadding);
            double y1 = (double) ((getMaxScore() - scores.get(i)) * yScale + padding);
            graphPoints.add(new Point2D.Double(x1, y1));
        }*/

        // draw white background
        g2.setColor(Color.WHITE);
        g2.fillRect(padding + labelPadding, padding, getWidth() - (2 * padding) - labelPadding, getHeight() - 2 * padding - labelPadding);
        g2.setColor(Color.BLACK);

        // create hatch marks and grid lines for y axis.
        for (int i = 0; i < numberYDivisions + 1; i++) {
            int x0 = padding + labelPadding;
            int x1 = pointWidth + padding + labelPadding;
            int y0 = getHeight() - ((i * (getHeight() - padding * 2 - labelPadding)) / numberYDivisions + padding + labelPadding);
            int y1 = y0;
            if (scores.size() > 0) {
                g2.setColor(gridColor);
                g2.drawLine(padding + labelPadding + 1 + pointWidth, y0, getWidth() - padding, y1);
                g2.setColor(Color.BLACK);
                String yLabel = ((int) ((getMinScore() + (getMaxScore() - getMinScore()) * ((i * 1.0) / numberYDivisions)) * 100)) / 100.0 + "";
                FontMetrics metrics = g2.getFontMetrics();
                int labelWidth = metrics.stringWidth(yLabel);
                g2.drawString(yLabel, x0 - labelWidth - 5, y0 + (metrics.getHeight() / 2) - 3);
            }
            g2.drawLine(x0, y0, x1, y1);
        }

        // and for x axis
        for (int i = 0; i < scores.size(); i++) {
            if (scores.size() > 1) {
                int x0 = i * (getWidth() - padding * 2 - labelPadding) / (scores.size() - 1) + padding + labelPadding;
                int x1 = x0;
                int y0 = getHeight() - padding - labelPadding;
                int y1 = y0 - pointWidth;
                if ((i % ((int) ((scores.size() / 20.0)) + 1)) == 0) {
                    g2.setColor(gridColor);
                    g2.drawLine(x0, getHeight() - padding - labelPadding - 1 - pointWidth, x1, padding);
                    g2.setColor(Color.BLACK);
                    String xLabel = i + "";
                    FontMetrics metrics = g2.getFontMetrics();
                    int labelWidth = metrics.stringWidth(xLabel);
                    g2.drawString(xLabel, x0 - labelWidth / 2, y0 + metrics.getHeight() + 3);
                }
                g2.drawLine(x0, y0, x1, y1);
            }
        }

        // create x and y axes
        g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, padding + labelPadding, padding);
        g2.drawLine(padding + labelPadding, getHeight() - padding - labelPadding, getWidth() - padding, getHeight() - padding - labelPadding);

        Stroke oldStroke = g2.getStroke();
        g2.setColor(lineColor);
        g2.setStroke(GRAPH_STROKE);
        for (int i = 0; i < graphPoints.size() - 1; i++) {
            double x1 = graphPoints.get(i).x;
            double y1 = graphPoints.get(i).y;
            double x2 = graphPoints.get(i + 1).x;
            double y2 = graphPoints.get(i + 1).y;
            g2.draw(new Line2D.Double(x1, y1, x2, y2));
        }

        g2.setStroke(oldStroke);
        g2.setColor(pointColor);
        for (int i = 0; i < graphPoints.size(); i++) {
            double x = graphPoints.get(i).x - pointWidth / 2;
            double y = graphPoints.get(i).y - pointWidth / 2;
            int ovalW = pointWidth;
            int ovalH = pointWidth;
            //g2.fillOval(x, y, ovalW, ovalH);
        }
    }

    public void findNearPoint(double x, double y) {
        double delta = 0;
        for (int j = 0; j < graphPoints.size(); j++) {
            double sx = graphPoints.get(j).x;
            double sy = graphPoints.get(j).y;
            double root = sqrt((x-sx)*(x-sx) + (y-sy)*(y-sy));
            if (j == 0) {
                delta = root;
                serieX = sx;
            }
            else if (root < delta) {
                serieX = sx;
                delta = root;
            }
        }
    }

    public void editSerie(double x, double y) {
        double tmpSerieX = serieX;
        int ind = 0;
        for (int i = 0; i < graphPoints.size(); i++) {
            if (graphPoints.get(i).x == tmpSerieX) {
                ind = i;
            }
        }
        graphPoints.remove(ind);
        graphPoints.add(ind, new Point2D.Double(x, y));
        serieX = x;
    }

    private double getMinScore() {
        double minScore = Double.MAX_VALUE;
        for (Double score : scores) {
            minScore = Math.min(minScore, score);
        }
        return minScore;
    }

    private double getMaxScore() {
        double maxScore = Double.MIN_VALUE;
        for (Double score : scores) {
            maxScore = Math.max(maxScore, score);
        }
        return maxScore;
    }

    public void setScores(List<Double> scores) {
        this.scores = scores;
        invalidate();
        this.repaint();
    }

    public List<Double> getScores() {
        return scores;
    }

    private static void createAndShowGui() {
        List<Double> scores = new ArrayList<>();
        Random random = new Random();
        int maxDataPoints = 40;
        int maxScore = 10;
        for (int i = 0; i < maxDataPoints; i++) {
            scores.add((double) random.nextDouble() * maxScore);
        }
        SimpleGrapher2 mainPanel = new SimpleGrapher2(scores);
        mainPanel.setPreferredSize(new Dimension(800, 600));
        JFrame frame = new JFrame("DrawGraph");
        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(new Runnable() {
         public void run() {
            createAndShowGui();
         }
      });
   }
}
解决方案

The problem is in your constructor when you calculate the x/yScale...

public SimpleGrapher2(List<Double> scores) {
    //...
    double xScale = ((double) getWidth() - (2 * padding) - labelPadding) / (scores.size() - 1);
    double yScale = ((double) getHeight() - 2 * padding - labelPadding) / (getMaxScore() - getMinScore());
    //...
}

At the point the component is constructed, the components size is 0x0. You need to wait until the component is resized in some meaningful way before calculating the points...

This is also problematic, as the component may be resized a number of times, in quick succession, when it is first realised onto the screen.

What I've done in the past is used a Swing Timer set to a smallish delay to allow the component to be resized a number of times over a small time scale. Once it's all settled down, the Timer will trigger and you can perform you required operations, for example...

public SimpleGrapher2(List<Double> scores) {
    //...
    addComponentListener(new ComponentAdapter() {

        private Timer initTimer = new Timer(200, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                initTimer.stop();
                double xScale = ((double) getWidth() - (2 * padding) - labelPadding) / (scores.size() - 1);
                double yScale = ((double) getHeight() - 2 * padding - labelPadding) / (getMaxScore() - getMinScore());

                graphPoints = new ArrayList<>();
                for (int i = 0; i < scores.size(); i++) {
                    double x1 = (double) (i * xScale + padding + labelPadding);
                    double y1 = (double) ((getMaxScore() - scores.get(i)) * yScale + padding);
                    graphPoints.add(new Point2D.Double(x1, y1));
                }
                repaint();
            }
        });

        @Override
        public void componentResized(ComponentEvent e) {
            if (graphPoints == null) {
                initTimer.restart();
            }
        }

    });

}

All this does is waits until the timer between the compoentResized event is more then 200 milliseconds (you can play with this value to get it closer to what you want, but I've found roughly 250 milliseconds to be a reasonable delay)

You will need to correct the paintComponent to allow for graphPoints been null as well.

这篇关于Java Swing - 重绘()无法正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 22:22