【问题标题】:Clicking a button within a JFrame passes an data to a JPanel单击 JFrame 中的按钮将数据传递给 JPanel
【发布时间】:2015-11-16 21:53:08
【问题描述】:

我有一个带有两个按钮的 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){

我想用 number.getNumber() 替换“A”

            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();
        }
    }
}

我不确定这是否可能。很抱歉,如果我的逻辑有误。请为我提供解决此问题的替代方法。感谢任何指导。

谢谢!

【问题讨论】:

  • 你的代码让我很困惑。您在这里使用的Number 类是什么Number number = new Number();?您使用的坐标类是什么?我看到这宣布无处可去。您在哪里将 ActionListener 添加到您的 JButton?你的 MouseListener 的目的是什么?您的问题陈述看起来非常简单,但您的代码看起来非常复杂且不必要(除非我误解了您的问题)。请准确说明您要实现的目标。
  • 真的很抱歉我没有包括这两个类。我只是错误地认为只有上面的代码是必要的。下次我会确保包括所有相关的类。我目前正在一步一步地做这个,所以包括我需要的东西。所以只有一个 JButton 实现了 ActionListener,因为我正在为此编写代码。我已经包含了 MouseListeners,因为我还有更多的鼠标功能要包含但还没有实现。
  • 为了将来参考,请浏览tour 并查看help center 部分以及how to ask good questions 部分。另请查看minimal reproducible example 部分,了解我们真正需要哪些代码,以及我们不需要哪些代码。这将使人们更容易理解您的问题并为您提供帮助。

标签: java swing jframe jpanel jbutton


【解决方案1】:

没有包含 Coordinates 和 Number 类,所以我不得不稍微修改一下代码。

这是我创建的 GUI。

我做的第一件事是为 GUI 创建一个模型类。通过创建模型类,我可以使显示字符串和绘图坐标可用于视图和控制器类。这是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 类。

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 方法在 Event Dispatch 线程上启动了 Java Swing 应用程序。

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

我为两个 JButton 使用了相同的 ButtonListener。我猜你想要什么,但我画的是“A”或“B”,这取决于你左键单击的按钮。

让我们看看 DrawPanel 类。

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();
        }

    }
}

我在这个类中所做的主要改变是使用了paintComponent 方法,而不是paint 方法。 paintComponent 方法是正确的重写方法。

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

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

我删除了鼠标运动侦听器代码,因为它不是必需的。

我希望这对您有所帮助。

【讨论】:

  • 很好的例子和解释! 1+
【解决方案2】:

好的,到目前为止我所知道的是,如果按下按钮,您希望 JPanel 中显示的文本发生变化。如果是这样,那么您的代码看起来对这项工作来说方式太复杂了。建议包括:

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

例如:

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 中显示文本更简单、更容易并且可能更好,因为将文本居中更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 2015-07-27
    • 1970-01-01
    相关资源
    最近更新 更多