如何在第二个窗口上多次获得结果而不是另一个打开?

时间:2018-02-15 13:08:45

标签: java swing jframe

我想制作一个简单的加法程序。在其中我想要将变量从Main_Window传递到Second_Window以进行添加,并且我希望多次在Second_Window上获得结果。意味着如果我从Main_Window多次传递变量以进行添加,那么结果应该在Second_Window而不是第三和第四Window

我希望所有更改都应在Second_Window上显示,而不是在打开时显示。

Here I want All changes should be show on <code>Second_Window</code> not another on open.

这些行是为从Main_Window传递变量而编写的。

Second_Window s = new Second_Window(a,b);
s.setVisible(true);

2 个答案:

答案 0 :(得分:1)

我将把我的previous answer代码作为基本代码提交给您的一个问题并添加一些功能:

首先,您需要创建第二个窗口的一个且仅一个实例,并且有一个方法可以更新发送给它的角度。

你如何做到这一点你可能会问自己,这很容易,在你的动作监听器中你创建实例,如果第二帧还没有创建,否则更新它。

private ActionListener listener = e -> {
    if (e.getSource().equals(submitButton)) {
        if (!frame.isVisible()) {
            circle = new MyCircle((Integer) box1.getSelectedItem(), (Integer) box2.getSelectedItem());
            frame.add(circle);
            frame.pack();
            frame.setVisible(true);
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        } else {
            circle.updateAngles((Integer) box1.getSelectedItem(), (Integer) box2.getSelectedItem());
        }
    }
};

注意:

如果关闭第二个窗口,之前的所有数据都将丢失,如果要保存该状态,请使用frame可见性并初始化MyCircle中的createAndShowGui()实例下面代码中的方法。

接下来你需要跟踪你添加的所有角度,因为你可能需要List并对其进行迭代,或者将其绘制到BufferedImage,然后绘制JPanel上的图片。对于此示例,我们将使用List选项。

但是,对于这个例子,如果数据太多,可能无法显示,为了纠正这个问题,也可以使用JScrollPane,但是我要把它留给你。

此示例也使整个程序仅在关闭主窗口时终止,但如果关闭第二个窗口则不会终止。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionListener;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class RadiusDrawer {
    private JFrame frame;
    private JFrame mainFrame;
    private int centerX = 50;
    private int centerY = 50;
    private int x1 = 0;
    private int y1 = 0;
    private int x2 = 0;
    private int y2 = 0;
    private int r = 100;

    private JComboBox<Integer> box1;
    private JComboBox<Integer> box2;
    private JLabel label1;
    private JLabel label2;
    private JButton submitButton;

    MyCircle circle;

    private static final Integer[] ANGLES = new Integer[]{15, 30, 45, 60, 75, 90};

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new RadiusDrawer()::createAndShowGui);
    }

    private void createAndShowGui() {
        frame = new JFrame(getClass().getSimpleName());
        mainFrame = new JFrame("Main Frame");

        mainFrame.add(createMainWindow());
        mainFrame.pack();
        mainFrame.setVisible(true);
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private ActionListener listener = e -> {
        if (e.getSource().equals(submitButton)) {
            if (!frame.isVisible()) {
                circle = new MyCircle((Integer) box1.getSelectedItem(), (Integer) box2.getSelectedItem());
                frame.add(circle);
                frame.pack();
                frame.setVisible(true);
                frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            } else {
                circle.updateAngles((Integer) box1.getSelectedItem(), (Integer) box2.getSelectedItem());
            }
        }
    };

    private JPanel createMainWindow() {
        JPanel pane = new JPanel();

        box1 = new JComboBox<>(ANGLES);
        box2 = new JComboBox<>(ANGLES);

        label1 = new JLabel("Angle 1");
        label2 = new JLabel("Angle 2");

        submitButton = new JButton("Submit");

        submitButton.addActionListener(listener);

        pane.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();

        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.insets = new Insets(20, 30, 20, 30);
        pane.add(box1, gbc);

        gbc.gridx = 1;
        pane.add(box2, gbc);

        gbc.gridx = 0;
        gbc.gridy = 1;
        pane.add(label1, gbc);

        gbc.gridx = 1;
        pane.add(label2, gbc);

        gbc.gridy = 2;
        pane.add(submitButton, gbc);

        return pane;
    }

    @SuppressWarnings("serial")
    class MyCircle extends JPanel {
        int cx = 0;
        int cy = 0;
        double lineX = 0;
        double lineY = 0;
        double roundedX = 0;
        double roundedY = 0;
        int angle1 = 0;
        int angle2 = 0;

        int angle1HistoryX = 15;
        int angle2HistoryX = 150;
        int angleHistoryY = 300;
        int angleHistoryYGap = 20;

        Color angle1Color = Color.BLUE;
        Color angle2Color = Color.RED;

        List <Integer> angle1History;
        List <Integer> angle2History;

        public MyCircle(int angle1, int angle2) {
            this.angle1 = angle1;
            this.angle2 = angle2;

            angle1History = new ArrayList<>();
            angle2History = new ArrayList<>();

            angle1History.add(angle1);
            angle2History.add(angle2);

            calculateCoords();
            calculateCenter();
        }

        private void updateAngles(int angle1, int angle2) {
            this.angle1 = angle1;
            this.angle2 = angle2;

            angle1History.add(angle1);
            angle2History.add(angle2);
            calculateCoords();

            this.revalidate();
            this.repaint();
        }

        private void calculateCoords() {
            x1 = (int) (r * Math.cos(Math.toRadians(angle1)));
            y1 = (int) (r * Math.sin(Math.toRadians(angle1))) * -1;

            x2 = (int) (r * Math.cos(Math.toRadians(angle2)));
            y2 = (int) (r * Math.sin(Math.toRadians(angle2))) * -1;
        }

        private void calculateCenter() {
            cx = centerX + r;
            cy = centerY + r;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;

            drawCircle(g2d, centerX, centerY, r);
            drawRadius(g2d);
            drawHistory(g2d);
        }

        private void drawCircle(Graphics2D g2d, int x, int y, int r) {
            g2d.setColor(Color.BLACK);
            g2d.draw(new Ellipse2D.Double(x, y, r * 2, r * 2));
        }

        private void drawRadius(Graphics2D g2d) {
            g2d.setColor(angle1Color);
            g2d.draw(new Line2D.Double(cx, cy, cx + x1, cy + y1));

            g2d.setColor(angle2Color);
            g2d.draw(new Line2D.Double(cx, cy, cx + x2, cy + y2));
        }

        private void drawHistory(Graphics2D g2d) {
            g2d.setColor(angle1Color);
            g2d.drawString("Angle1", angle1HistoryX, angleHistoryY);
            for (int i = 0; i < angle1History.size(); i++) {
                g2d.drawString(angle1History.get(i).toString(), angle1HistoryX, angleHistoryY + (angleHistoryYGap * (i + 1)));
            }

            g2d.setColor(angle2Color);
            g2d.drawString("Angle2", angle2HistoryX, angleHistoryY);
            for (int i = 0; i < angle2History.size(); i++) {
                g2d.drawString(angle2History.get(i).toString(), angle2HistoryX, angleHistoryY + (angleHistoryYGap * (i + 1)));
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(300, 600);
        }
    }
}

就是这样!

enter image description here enter image description here

答案 1 :(得分:0)

所以基本上你想让第二个窗口保持最大一个实例(如果永远不会点击主窗口中的按钮,则为零),要做到这一点,你需要保持对第二个窗口的静态引用,如果这个引用已经存在,您不创建新的,但要求现有的显示计算结果。

可能的方法:

对于主窗口中的提交按钮,您将收集所需参数的值,并调用第二个窗口类的静态方法。静态方法是属于类的方法,而不是对象。

    btnSubmit.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent aE) {
            int azimuth = ...;
            int elevation = ...;

            SecondWindow.showResult(azimuth, elevation);
        }
    });

在第二个窗口类中,它保留此类的静态实例,最初为null。当调用showResult()时,它会检查实例是否尚不存在,然后创建一个新的第二个窗口并分配给静态引用。它要求实例计算并在UI中显示结果。

public class SecondWindow extends JFrame {
    private static SecondWindow instance = null;

    public static void showResult(int azimuth, int elevation) {
        if (instance == null) {
            instance = new SecondWindow();
        }

        instance.performShowResult(azimuth, elevation);
    }

    private void performShowResult(int azimuth, int elevation) {
        // Display the result in UI.
    }
}

最后要考虑的是,是否要在关闭实例时将其设置为null?如果是,请将此代码添加到第二个窗口构造函数:

public SecondWindow() {
    addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent aE) {
            instance = null;
        }
    });
}

因此,再次调用showResult()时,将创建一个新的第二个窗口。

如果您认为第二个窗口的创建有点“沉重”,那么您可以保持第二个窗口关闭(因此不将实例设置为null),但确保在调用showResult()时显示它。像这样:

public static void showResult(int azimuth, int elevation) {
    if (instance == null) {
        instance = new SecondWindow();
    } else if (instance.isShowing() == false) {
        instance.setVisible(true);
    }

    instance.performShowResult(azimuth, elevation);
}