关于swing:调用java方法绘制图形

calling a java method to draw graphics

我正在尝试在框架上绘制一些简单的图形。我还希望能够调整我从我的主要方法中绘制的内容。例如,设置要打印的字符串变量,或者矩形的坐标。

我似乎遇到的问题是在设置类变量之前调用了 paintComponent 方法。我将如何更改此代码以便能够在它绘制到屏幕之前设置 JPanel/JFrame 变量?

谢谢

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.awt.*;
import javax.swing.*;

public class Test {

    public static void main(String[] args) {
        FrameTest test_frame = new FrameTest();
        test_frame.test_string ="I WANT TO DRAW THIS STRING";
    }
}

class FrameTest extends JFrame{
    private static final long serialVersionUID = 1L;
    String test_string;

    public FrameTest(){
        this.test_string ="TEMP STRING FROM FRAME";
        JFrame gui = new JFrame();
        gui.setTitle("Test Title");
        gui.setSize(400,400);
        gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Painting painting = new Painting();

        Container pane = gui.getContentPane();
        pane.setLayout(new GridLayout(1,1));

        pane.add(painting);
        gui.setVisible(true);

    }
}

class Painting extends JPanel{
    private static final long serialVersionUID = 1L;
    String test_string;

    public Painting(){
        setBackground(Color.WHITE);
        this.test_string ="TEMP STRING FROM PANEL";
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.RED);
        g.drawString(test_string, 20, 20);
    }
}


从 FrameTest 类中删除 test_string。直接使用 set 方法设置 test_string。参见示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.awt.GridLayout;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

    public static void main(String[] args) {
        FrameTest1 test_frame = new FrameTest1();
        test_frame.setContentString("I WANT TO DRAW THIS STRING");
    }

}

class FrameTest1 extends JFrame {
    private static final long serialVersionUID = 1L;

    Painting painting = new Painting();

    public FrameTest1() {
        JFrame gui = new JFrame();
        gui.setTitle("Test Title");
        gui.setSize(400, 400);
        gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container pane = gui.getContentPane();
        pane.setLayout(new GridLayout(1, 1));

        pane.add(painting);
        gui.setVisible(true);

    }

    public void setContentString(String value) {
        painting.test_string = value;
    }
}

class Painting extends JPanel {
    private static final long serialVersionUID = 1L;
    String test_string;

    public Painting() {
        setBackground(Color.WHITE);
        this.test_string ="TEMP STRING FROM PANEL";
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.RED);
        g.drawString(test_string, 20, 20);
    }
}

在这里,您将一个字符串分配给 FrameTest 中的 test_string,它不会更新 Painting:

中的同名变量

1
test_frame.test_string ="I WANT TO DRAW THIS STRING";

为什么不向 FrameTest 添加一个更新方法,因为您对此有参考:

1
2
3
public void setTestString(String test_string) {
    painting.setTestString(test_string);
}

并调用:

1
2
FrameTest test_frame = new FrameTest();
test_frame.setTestString("I WANT TO DRAW THIS STRING");

注意:Java 使用 CamelCase,例如testString


For example, setting a String variable to be printed, or the coordinates of a rectangle.

main(String[])中创建一个BufferedImage,有一个Painting.setImage(Image)的方法,在JLabel中显示图像。

这更通用,因为它可以接受字符串的图像,或椭圆的图像,或在渐变 BG 上的椭圆的一部分上的字符串的图像..

显示许多图像

Many

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.Random;

public class ImageViewer {
   
    JPanel gui;
    /** Displays the image. */
    JLabel imageCanvas;

    /** Set the image as icon of the image canvas (display it). */
    public void setImage(Image image) {
        imageCanvas.setIcon(new ImageIcon(image));
    }
   
    public void initComponents() {
        if (gui==null) {
            gui = new JPanel(new BorderLayout());
            gui.setBorder(new EmptyBorder(5,5,5,5));
            imageCanvas = new JLabel();
           
            JPanel imageCenter = new JPanel(new GridBagLayout());
            imageCenter.add(imageCanvas);
            JScrollPane imageScroll = new JScrollPane(imageCenter);
            imageScroll.setPreferredSize(new Dimension(300,100));
            gui.add(imageScroll, BorderLayout.CENTER);
        }
    }
   
    public Container getGui() {
        initComponents();
        return gui;
    }
   
    public static Image getRandomImage(Random random) {
        int w = 100 + random.nextInt(400);
        int h = 50 + random.nextInt(200);
        BufferedImage bi = new BufferedImage(
                w,h,BufferedImage.TYPE_INT_RGB);
       
        return bi;
    }

    public static void main(String[] args) throws Exception {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                JFrame f = new JFrame("Image Viewer");
                // TODO Fix kludge to kill the Timer
                f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           
                final ImageViewer viewer = new ImageViewer();
                f.setContentPane(viewer.getGui());
               
                f.pack();
                f.setLocationByPlatform(true);
                f.setVisible(true);

                ActionListener animate = new ActionListener() {

                    Random random = new Random();
                   
                    @Override
                    public void actionPerformed(ActionEvent arg0) {
                        viewer.setImage(getRandomImage(random));
                    }
                };
                Timer timer = new Timer(1500,animate);
                timer.start();
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

您可以通过构造函数将要绘制的文本传递给Painting 类,也可以将绘画传递给FrameSet。

要了解有关 java 构造函数和参数的更多信息,请阅读以下内容:http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html

我已经修改了你的代码来满足你的需要,不过我还没有测试过。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import java.awt.*;
import javax.swing.*;

public class Test {

    public static void main(String[] args) {
        Painting painting = new Painting("I WANT TO DRAW THIS STRING");
        FrameTest test_frame = new FrameTest(painting);
    }
}

class FrameTest extends JFrame{
    private static final long serialVersionUID = 1L;
    String test_string;

    public FrameTest(painting){
        super();
        this.test_string ="TEMP STRING FROM FRAME";
        JFrame gui = new JFrame();
        gui.setTitle("Test Title");
        gui.setSize(400,400);
        gui.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        Container pane = gui.getContentPane();
        pane.setLayout(new GridLayout(1,1));

        pane.add(painting);
        gui.setVisible(true);

    }
}

class Painting extends JPanel{
    private static final long serialVersionUID = 1L;
    String test_string;

    public Painting(String test_string){
        super();
        this.test_string = test_string;
        setBackground(Color.WHITE);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.setColor(Color.RED);
        g.drawString(test_string, 20, 20);
    }
}