单击 JFrame 中的按钮将数据传递给 JPanel

Clicking a button within a JFrame passes an data to a JPanel

我有一个带有两个按钮的 Jframe:“1”和“2”。单击按钮“1”应该会在 JPanel 中显示大写字母 A。

我的 JFrame 的代码:

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class DrawFrame extends JFrame{
    private final int WIDTH = 500;
    private final int HEIGHT = 300;

    private JButton number1;
    private JButton number2;

    private JPanel numberPanel;
    private DrawPanel graphicsPanel;

    public DrawFrame()
    {
        createSelectionPanel();
        createGraphicsPanel();

        this.setSize(WIDTH, HEIGHT);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setVisible(true);
    }

    private void createSelectionPanel()
    {
        numberPanel = new JPanel();

        number1 = new JButton("1");
        number2 = new JButton("2");   

        numberPanel.setLayout(new GridLayout(2,2));
        numberPanel.add(number1);
        numberPanel.add(number2);

        this.add(numberPanel, BorderLayout.WEST);
    }

    private void createGraphicsPanel()
    {
        //instantiate drawing panel
        graphicsPanel = new DrawPanel();
        //add drawing panel to right
        add(graphicsPanel);
    }

    private class Number1ButtonListener implements ActionListener {
        public void actionPerformed (ActionEvent event) {
            Number number = new Number();
            number.setNumber('A');
        }
    }

    //creates a drawing frame
    public static void main(String[] args)
    {
        DrawFrame draw = new DrawFrame();
    }   
}

我的 JPanel 的代码

import javax.swing.JPanel;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

public class DrawPanel extends JPanel{
    public Coordinates current;

    public DrawPanel(){
        //nothing drawn initially
        current = null;

        //set white background for drawing panel
        setBackground(Color.WHITE);

        //add mouse listeners
        MouseHandler mouseHandler = new MouseHandler();
        this.addMouseListener(mouseHandler);
        this.addMouseMotionListener(mouseHandler);
    }

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

        if(current!=null){

I want to replace "A" with number.getNumber()

            g.drawString("A", current.getX(), current.getY());
        }
    }

    //class to handle all mouse events
    private class MouseHandler extends MouseAdapter implements MouseMotionListener
    {
        public void mousePressed(MouseEvent event)
        {
           current = new Coordinates(event.getX(), event.getY());
        }

        public void mouseReleased(MouseEvent event)
        {
            repaint();
        }
    }
}

我不确定这是否可行。很抱歉,如果我的逻辑有误。请为我提供另一种方法来解决这个问题。感谢任何指导。

谢谢!

好的,目前我所知道的是您希望 JPanel 中显示的文本在按下按钮时发生变化。如果是这样,那么您的代码看起来 way 太复杂了。建议包括:

  • 为 DrawingPanel 提供一个 setter 方法,例如 setText(String text),它允许外部 类 更改它显示的文本。
  • 在该方法中,设置 DrawingPanel 的一个字段,假设名为 text,然后调用 repaint()
  • 覆盖 DrawingPanel 的 paintComponent 而不是其 paint 方法,并在您的覆盖内调用超级方法。
  • 在 paintComponent 方法中,调用 drawString 绘制文本字段持有的字符串,如果该字段不为空。
  • 为您的按钮提供调用 DrawingPanel 的 setText(...) 方法的 ActionListeners 或 AbstractActions,设置要显示的文本。

例如:

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;

import javax.swing.*;

public class DrawAorB extends JPanel {
    private DrawingPanel drawingPanel = new DrawingPanel(); 

    public DrawAorB() {
        JPanel btnPanel = new JPanel(new GridLayout(1, 0, 5, 5));
        btnPanel.add(new JButton(new ButtonAction("A")));
        btnPanel.add(new JButton(new ButtonAction("B")));

        setLayout(new BorderLayout());
        add(drawingPanel, BorderLayout.CENTER);
        add(btnPanel, BorderLayout.PAGE_END);
    }

    private class ButtonAction extends AbstractAction {
        public ButtonAction(String name) {
            super(name);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            String text = e.getActionCommand();
            drawingPanel.setText(text);
        }
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("DrawAorB");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new DrawAorB());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

class DrawingPanel extends JPanel {
    private static final int PREF_W = 200;
    private static final int PREF_H = PREF_W;
    private String text = null;

    public void setText(String text) {
        this.text = text;  // set the JPanel's text
        repaint();  // and draw it
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (text != null) {
            int x = getWidth() / 2;
            int y = getHeight() / 2;
            // use FontMetrics if you want to center text better
            g.drawString(text, x, y);
        }
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(PREF_W, PREF_H);
    }
}

在 JLabel 中显示文本甚至更简单、更容易并且可能更好,因为它更容易将文本居中。

没有包含坐标和数字 classes,所以我不得不稍微修改一下代码。

这是我创建的 GUI。

我做的第一件事是为 GUI 创建一个模型 class。通过创建模型 class,我可以使显示字符串和绘图坐标可用于视图和控制器 classes。这是 model / view / controller pattern.

的简单示例
package com.ggl.drawing;

import java.awt.Point;

public class GUIModel {

    private String displayString;

    private Point coordinate;

    public GUIModel(String displayString) {
        this.displayString = displayString;
    }

    public Point getCoordinate() {
        return coordinate;
    }

    public void setCoordinate(int x, int y) {
        this.coordinate = new Point(x, y);
    }

    public void setCoordinate(Point coordinate) {
        this.coordinate = coordinate;
    }

    public void setDisplayString(String displayString) {
        this.displayString = displayString;
    }

    public String getDisplayString() {
        return displayString;
    }

}

现在我们有了一个模型,让我们看看 DrawFrame class。

package com.ggl.drawing;

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class DrawFrame implements Runnable {
    private final int WIDTH = 500;
    private final int HEIGHT = 300;

    private JFrame frame;

    private GUIModel model;

    public DrawFrame() {
        this.model = new GUIModel("A");
    }

    @Override
    public void run() {
        frame = new JFrame("Draw Letters");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createSelectionPanel(), BorderLayout.WEST);
        frame.add(new DrawPanel(WIDTH, HEIGHT, model), BorderLayout.CENTER);

        frame.pack();
        frame.setVisible(true);
    }

    private JPanel createSelectionPanel() {
        JPanel numberPanel = new JPanel();
        ButtonListener listener = new ButtonListener();

        JButton number1 = new JButton("A");
        number1.addActionListener(listener);

        JButton number2 = new JButton("B");
        number2.addActionListener(listener);

        numberPanel.setLayout(new GridLayout(0, 2));
        numberPanel.add(number1);
        numberPanel.add(number2);

        return numberPanel;
    }

    private class ButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent event) {
            model.setDisplayString(event.getActionCommand());
        }
    }

    // creates a drawing frame
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new DrawFrame());
    }
}

我通过调用 SwingUtilities invokeLater 方法在事件调度线程上启动了 Java Swing 应用程序。

我将 JFrame 构造与 2 JPanels 构造分开了。我使用了 JFrame,而不是扩展 JFrame。唯一应该扩展任何 Java class 的情况是,如果您想覆盖一个或多个 class 方法。

我对两个 JButton 使用了相同的 ButtonListener。我猜你想要什么,但我画了 "A" 或 "B",具体取决于你左键单击的按钮。

让我们看看DrawPanel class。

package com.ggl.drawing;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JPanel;

public class DrawPanel extends JPanel {

    private static final long serialVersionUID = 3443814601865936618L;

    private GUIModel model;

    public DrawPanel(int width, int height, GUIModel model) {
        this.setPreferredSize(new Dimension(width, height));
        this.model = model;
        // add mouse listeners
        MouseHandler mouseHandler = new MouseHandler();
        this.addMouseListener(mouseHandler);
    }

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

        if (model.getCoordinate() != null) {
            Point p = model.getCoordinate();
            Font font = g.getFont().deriveFont(48F);
            g.setFont(font);
            g.drawString(model.getDisplayString(), p.x, p.y);
        }
    }

    // class to handle all mouse events
    private class MouseHandler extends MouseAdapter {

        @Override
        public void mousePressed(MouseEvent event) {
            model.setCoordinate(event.getPoint());
        }

        @Override
        public void mouseReleased(MouseEvent event) {
            DrawPanel.this.repaint();
        }

    }
}

我在此 class 中所做的主要更改是使用 paintComponent 方法,而不是 paint 方法。 paintComponent 方法是要覆盖的正确方法。

我在 DrawPanel 构造函数中设置绘图面板的大小。最好让 Swing 计算出 JFrame 的大小。这就是 DrawFrame 运行 方法中的 pack 方法所做的。

我增加了字体大小,以便您可以更好地看到绘制的字母。

我删除了鼠标动作侦听器代码,因为不需要它。

希望对您有所帮助。