简体   繁体   English

有没有办法从同一类中的另一个方法在JPanel上绘制形状?

[英]Is there a way to draw shapes on a JPanel from another method inside same class?

I am working to develop a GUI in which I paint some 2D shapes repeatedly on different locations. 我正在开发一个GUI,在其中可以在不同位置重复绘制一些2D形状。 Currently I am having a method createGUI() that creates the basic layout and the panels and then I call the constructor for the content_panel to create 2D shapes in the content_panel. 当前,我有一个createGUI()方法,用于创建基本布局和面板,然后调用content_panel的构造函数在content_panel中创建2D形状。

But, I want to use another method to create the shapes in the main JPanel. 但是,我想使用另一种方法在主JPanel中创建形状。 Is there a way in Java, so that I can have two method calls in main. Java中有没有一种方法,这样我可以在main中进行两个方法调用。 First method createGUI() creates the GUI including JFrames and JPanel. 第一个方法createGUI()创建包含JFrames和JPanel的GUI。 While the second method createShapes() creates shapes in the one specific JPanel - content_panel. 第二种方法createShapes()在一个特定的JPanel-content_panel中创建形状。 I would like to call this createShapes() method repeatedly and pass different arguments to see shapes at different locations. 我想反复调用此createShapes()方法,并传递不同的参数以查看不同位置的形状。

Please let me know if you need some more info or the question is unclear. 如果您需要更多信息,或者问题不清楚,请告诉我。 Thanks 谢谢

Code: 码:

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

public class Board{

public static void main(String[] args)
{
    createGUI();
    drawShapes();
}

//This method creates the basic GUI 
private static void createGUI()
{
    //Creating the JFrame main window
    JFrame mainFrame = new JFrame();
    mainFrame.setSize(800, 500);
    mainFrame.setTitle("Particle Filter");
    mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    mainFrame.setLocation(100, 100);
    mainFrame.getContentPane().setLayout(new BoxLayout(mainFrame.getContentPane(), BoxLayout.X_AXIS));

    //creates two panels content and sidebar. Sidebar has null layout       
    JPanel content = new JPanel();
    content.setPreferredSize(new Dimension(700,500));
    content.setBackground(Color.LIGHT_GRAY);
    mainFrame.getContentPane().add(content);
    JPanel sidebar = new JPanel();
    sidebar.setBackground(Color.LIGHT_GRAY);
    sidebar.setPreferredSize(new Dimension(100,500));
    mainFrame.getContentPane().add(sidebar);
    sidebar.setLayout(null);

    //creates three buttons in sidebar
    JButton start_button = new JButton("START");
    start_button.setBounds(10, 75, 77, 23);
    sidebar.add(start_button);
    JButton stop_button = new JButton("STOP");
    stop_button.setBounds(10, 109, 77, 23);
    sidebar.add(stop_button);
    JButton reset_button = new JButton("RESET");
    reset_button.setBounds(10, 381, 77, 23);
    sidebar.add(reset_button);

    //calls the content_Walls class and sends the number of ovals to be generated
    int n=1000; // n denotes the number of ovals
    content.add( new Content_Walls(n));
    mainFrame.setVisible(true);

}

private static void drawShapes()
{

}

}
    class Content_Walls extends JPanel
    {


    ArrayList<Integer> list;

    Content_Walls(int n)
    {
        setPreferredSize(new Dimension(680,450));
        setBackground(Color.WHITE);
        list = new ArrayList<Integer>(Collections.nCopies(n, 0));
    }       

    public void paintComponent(Graphics g)
    {
        int x=0,y=0;
        super.paintComponent(g);

        createObstacles(g,150,225,100,40);
        createObstacles(g,500,300,40,100);

        for(int i=0;i<list.size();i++)
        {
            x=randomInteger(11,670); // bounds of x between which the particles should be generated 
            y=randomInteger(11,440); // bounds of y between which the particles should be generated 

            int radius = 4;

            x=x-(radius/2);
            y=y-(radius/2);
            g.fillOval(x, y, radius, radius);
        }

    private void createObstacles(Graphics g, int x, int y, int width, int height)
    {
        g.setColor(Color.BLACK);
        g.fillRect(x, y, width, height);
    }


    private static int randomInteger(int min, int max)
    {
        Random rand = new Random();
        int randomNum = rand.nextInt((max - min) + 1) + min;
        return randomNum;
    }
}

There are all sorts of problems with your code. 您的代码有各种各样的问题。

  1. You're creating Swing components on the main thread instead of the Event Dispatch Thread. 您正在主线程上而不是在事件调度线程上创建Swing组件。 Search for help on this. 搜索有关此的帮助。

  2. Have Board subclass JFrame and do the GUI initialization in the constructor or an instance method instead of a static method. 使用Board子类JFrame并在构造函数或实例方法(而非静态方法)中进行GUI初始化。

  3. Make drawShapes() an instance method. 使drawShapes()成为实例方法。

  4. When you create the JPanel , store its reference in an instance variable (eg, myPanel ). 创建JPanel ,将其引用存储在实例变量(例如, myPanel )中。 This will be easier to do and will be a lot less messy if you fix #2. 如果您修复了#2,这样做会更容易,也不会太混乱。

  5. If you do #2 and #3, just pass the reference to the drawShapes() method. 如果执行#2和#3,则只需将引用传递给drawShapes()方法即可。

  6. drawShapes() might not even be needed, if all the logic is in the paintComponent() method. 如果所有逻辑都在paintComponent()方法中,则可能甚至不需要drawShapes() Call myPanel.repaint() to invoke the paintComponent() method. 调用myPanel.repaint()以调用paintComponent()方法。

You should use event dispatching to let different JPanels component to act on the event. 您应该使用事件调度来让不同的JPanels组件对事件进行操作。

eg You could attach a custom event with an event type and jpanel id; 例如,您可以附加一个带有事件类型和jpanel ID的自定义事件; and then fire the event from the main. 然后从主要触发事件。 The panel listening to the event do something based on the logic. 聆听事件的面板会根据逻辑执行某些操作。

Each JPanel listening to the event will intercept the event and if the jpanelid in the event matches to its own jpanel id, it will draw the shape. 每个监听事件的JPanel都会截获该事件,并且如果事件中的jpanelid与其自己的jpanel ID匹配,它将绘制形状。

I hope you get a pointer. 我希望你能得到一个指示。

Here is a sample code, which I have not tested, but it shows how could you use event dispatching/listening to communicate between GUI components. 这是一个示例代码,我尚未测试过,但是它显示了如何使用事件分派/侦听在GUI组件之间进行通信。

Define a ChangeEventListener interface 定义一个ChangeEventListener接口

public interface ChangeEventListener {
    public void stateChanged(ChangeEvent e);
}

And define an Event 并定义一个事件

public class ChangeEvent {

    private Object source;
    private int jPanelId;

    public ChangeEvent(Object source, int jPanelId) {
        this.source = source;
        this.jPanelId= jPanelId;
    }

    public Object getSource() {
        return source;
    }

    public int getJPanelId() {
        return jPanelId;
    }

}

Define your panel like 像定义您的面板

public class ShapePanel extends JPanel {

private int jPanelId;

private ChangeEventListener changeEventListener;

public void ShapePanel(int jPanelId){
this.jPanelId = jPanelId;
}

/*
.............
.............. Other code
.................
*/

public void addChangeEventListener(ChangeEventListener changeEventListener) {
        this.changeEventListener = changeEventListener;
    }

public int getJPanelId(){
   return jPanelId;
 }

public getChangeEventListener(){
   return changeEventListener;
 }
}

Your main should contain something like; 您的主要内容应包含类似内容;

// Craete different Jpanel
JPanel squareShapePanel = new ShapePanel(1);
JPanel roundShapePanel = new ShapePanel(2);
JPanel triangleShapePanel = new ShapePanel(3);

// Attach event listener with each one like
squareShapePanel.addChangeEventListener(new ChangeEventListener() {
    @Override
    public void stateChanged(ChangeEvent e) {
      if(e.getJPanelId() == squareShapePanel.getJPanelId()){
      // Createshape method can be available inside JPanel code
      // something like squareShapePanel.craeteShape();
      // All in one it is a method which could do something for you on the event.
      // Assuming that it is available in current class
      createShape("square");
    }
});

/*
Similarly attach eventlistener with each panels.
*/
// to draw the square shape, Fire change event
ChangeEvent event = new ChangeEvent(new String("Main"),1);

squareShapePanel.getChangeEventListener().stateChanged(event);

Hope this helps. 希望这可以帮助。

Check out Custom Painting Approaches for the two common ways to do custom painting: 查看“ 自定义绘画方法”,以了解两种常见的自定义绘画方法

  1. Keep the Shapes you want to paint in an List and then just paint all the Shapes in the List 将要绘制的形状保留在列表中,然后仅绘制列表中的所有形状
  2. Use a BufferedImage and just draw the Shapes onto the BufferedImage. 使用BufferedImage并将形状绘制到BufferedImage上。

Both examples contain an addRectangle(...) method that allows you to dynamically add a Rectangle to be painted. 这两个示例都包含一个addRectangle(...)方法,该方法允许您动态添加要绘制的Rectangle。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM