【问题标题】:Java, draw on a specific JPanelJava,在特定的 JPanel 上绘制
【发布时间】:2016-11-25 20:33:53
【问题描述】:

我正在开发一个程序,该程序根据用户给出的输入绘制线性函数。 我设法创建了一种绘制“线”(很多点)的方法。

正如您在屏幕截图中看到的,右侧有一些空间。我想添加一些 JButtons、JLabels 和 JTextFields 以便用户可以输入函数的数据。

Screenshot of the program

但如果我添加一些 JButton 或一些 JLabel,它们将不会显示在右侧。谁能解释我这种行为的原因?我将上传不带 JButton 的版本的源代码。 谢谢大家的帮助!

package projekt;

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

public class ProjectFunction extends JFrame {


    public ProjectFunction() {


        setLayout(new BorderLayout());


        setSize(1900, 1000);
        setTitle("First Test");
        setVisible(true);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
    }


    public void paint(Graphics g){
        g.setColor(new Color(204, 204, 204));
        g.drawLine(0, 900, 1000, 900);
        g.drawLine(0, 800, 1000, 800);
        g.drawLine(0, 700, 1000, 700);
        g.drawLine(0, 600, 1000, 600);
        g.drawLine(0, 400, 1000, 400);
        g.drawLine(0, 300, 1000, 300);
        g.drawLine(0, 200, 1000, 200);
        g.drawLine(0, 100, 1000, 100);
        g.drawLine(100, 0, 100, 1000);
        g.drawLine(200, 0, 200, 1000);
        g.drawLine(300, 0, 300, 1000);
        g.drawLine(400, 0, 400, 1000);
        g.drawLine(600, 0, 600, 1000);
        g.drawLine(700, 0, 700, 1000);
        g.drawLine(800, 0, 800, 1000);
        g.drawLine(900, 0, 900, 1000);
        g.setColor(Color.BLACK);
        g.drawRect(0, 500, 1000, 1);
        g.drawRect(500, 0, 1, 1000);
        g.setColor(Color.RED);
        linear(0.25, 1, g);
        g.setColor(Color.BLUE);
        linear(-3, -2.5, g);

    }


    public void linear(double s, double c, Graphics g) {
        int Anzpunkte = 0;
        c = c * 100;
        int x = 500, y = 500 - (int) c;
        g.drawOval(x, y, 2, 2);
        y = y - (int) s;
        double abtrag = s - (int) s;
        System.out.println("Punkt   X-Achse  Y-Achse   Abtrag   Steigung");
        Anzpunkte++;
        System.out.println("" + Anzpunkte + "      " + x + "      " + y + "       " + abtrag + "   " + s);
        while (x < 1000 && y < 1000 && x > 0 && y > 0) {
            x++;
            g.drawOval(x, y, 2, 2);
            Anzpunkte++;
            System.out.println("" + Anzpunkte + "      " + x + "      " + y + "       " + abtrag + "   " + s);
            if (abtrag >= 1 || abtrag <= -1) {
                y = y - (int) s;
                y = y - (int) abtrag;
                abtrag = s - (int) s;
            } else {
                y = y - (int) s;
                abtrag = abtrag + s - (int) s;
            }
        }
        x = 500;
        y = 500 - (int) c;
        while (x < 1000 && y < 1000 && x > 0 && y > 0) {
            x--;
            g.drawOval(x, y, 2, 2);
            Anzpunkte++;
            System.out.println("" + Anzpunkte + "      " + x + "      " + y + "       " + abtrag + "   " + s);
            if (abtrag >= 1 || abtrag <= -1) {
                y = y + (int) s;
                y = y + (int) abtrag;
                abtrag = s - (int) s;
            } else {
                y = y + (int) s;
                abtrag = abtrag + s - (int) s;
            }
        }


    }


    public static void main(String[] args) {
        ProjectFunction p = new ProjectFunction();


    }

}

【问题讨论】:

  • 在您发布的任何地方都没有添加任何按钮或标签组件的代码。
  • 欢迎来到 Stack Overflow!请查看我们的SO Question Checklist 以帮助您提出一个好问题,从而得到一个好的答案。

标签: java swing jframe jpanel draw


【解决方案1】:

如果您想在右侧添加按钮,您将需要了解和使用布局管理器。一个关键概念是,您可以通过嵌套 JPanel 来有效地嵌套布局,每个 JPanel 都使用自己的布局。例如,如果我们在 JPanel 中进行绘图(建议这样做而不是直接在 JFrame 中进行绘图,我们可以将此 JPanel 放在另一个 JPanel 中,该 JPanel 在 BorderLayOut.CENTER 位置使用 BorderLayout。然后我们可以添加另一个 JPanel使用 GridLayout 将按钮添加到这个外部 JPanel 的右侧。

也许最好只显示一个例子:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;

import javax.swing.*;

public class ProjectFunctionTest {
    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> {
            JFrame mainFrame = new JFrame("Project Function");
            mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            mainFrame.add(new ProjFunctMainPanel());
            mainFrame.pack();
            mainFrame.setLocationRelativeTo(null);
            // mainFrame.setExtendedState(JFrame.MAXIMIZED_BOTH);
            mainFrame.setVisible(true);
        });
    }
}

class ProjFunctMainPanel extends JPanel {
    private static final String[] BUTTON_TEXTS = {"Open", "Save", "Edit", "Exit"};
    private ProjFunctDrawingPanel drawingPanel = new ProjFunctDrawingPanel();

    public ProjFunctMainPanel() {
        // an inner jpanel to hold our jbuttons and uses grid layout
        JPanel buttonPanel = new JPanel(new GridLayout(0, 1, 5, 5));
        for (String btnText : BUTTON_TEXTS) {
            buttonPanel.add(new JButton(btnText));
        }

        // a wrapper jpanel to hold the button panel above at its top
        // so the buttons are loaded top-right
        JPanel rightPanel = new JPanel(new BorderLayout());
        rightPanel.add(buttonPanel, BorderLayout.PAGE_START);

        // make outer panel use borderlayout
        setLayout(new BorderLayout());
        add(drawingPanel, BorderLayout.CENTER); // add drawing to the center
        add(rightPanel, BorderLayout.LINE_END);  // and wrapper panel with buttons to the right
    }
}

class ProjFunctDrawingPanel extends JPanel {
    private static final int PANEL_W = 1000;
    private static final int PANEL_H = 900;

    public ProjFunctDrawingPanel() {
        setBorder(BorderFactory.createLineBorder(Color.BLUE));
    }

    // this will set the preferred size of the jpanel to be one that fits the image
    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();            
        } else {
            return new Dimension(PANEL_W, PANEL_H);
        }
    }

    // draw in a JPanel's paintComponent method
    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g); // don't forget to call the super's method
        g.setColor(new Color(204, 204, 204));
        g.drawLine(0, 900, 1000, 900);
        g.drawLine(0, 800, 1000, 800);
        g.drawLine(0, 700, 1000, 700);
        g.drawLine(0, 600, 1000, 600);
        g.drawLine(0, 400, 1000, 400);
        g.drawLine(0, 300, 1000, 300);
        g.drawLine(0, 200, 1000, 200);
        g.drawLine(0, 100, 1000, 100);
        g.drawLine(100, 0, 100, 1000);
        g.drawLine(200, 0, 200, 1000);
        g.drawLine(300, 0, 300, 1000);
        g.drawLine(400, 0, 400, 1000);
        g.drawLine(600, 0, 600, 1000);
        g.drawLine(700, 0, 700, 1000);
        g.drawLine(800, 0, 800, 1000);
        g.drawLine(900, 0, 900, 1000);
        g.setColor(Color.BLACK);
        g.drawRect(0, 500, 1000, 1);
        g.drawRect(500, 0, 1, 1000);
        g.setColor(Color.RED);
        linear(0.25, 1, g);
        g.setColor(Color.BLUE);
        linear(-3, -2.5, g);
    }

    public void linear(double s, double c, Graphics g) {
        int Anzpunkte = 0;
        c = c * 100;
        int x = 500, y = 500 - (int) c;
        g.drawOval(x, y, 2, 2);
        y = y - (int) s;
        double abtrag = s - (int) s;
        System.out.println("Punkt   X-Achse  Y-Achse   Abtrag   Steigung");
        Anzpunkte++;
        System.out.println("" + Anzpunkte + "      " + x + "      " + y + "       " + abtrag + "   " + s);
        while (x < 1000 && y < 1000 && x > 0 && y > 0) {
            x++;
            g.drawOval(x, y, 2, 2);
            Anzpunkte++;
            System.out.println("" + Anzpunkte + "      " + x + "      " + y + "       " + abtrag + "   " + s);
            if (abtrag >= 1 || abtrag <= -1) {
                y = y - (int) s;
                y = y - (int) abtrag;
                abtrag = s - (int) s;
            } else {
                y = y - (int) s;
                abtrag = abtrag + s - (int) s;
            }
        }
        x = 500;
        y = 500 - (int) c;
        while (x < 1000 && y < 1000 && x > 0 && y > 0) {
            x--;
            g.drawOval(x, y, 2, 2);
            Anzpunkte++;
            System.out.println("" + Anzpunkte + "      " + x + "      " + y + "       " + abtrag + "   " + s);
            if (abtrag >= 1 || abtrag <= -1) {
                y = y + (int) s;
                y = y + (int) abtrag;
                abtrag = s - (int) s;
            } else {
                y = y + (int) s;
                abtrag = abtrag + s - (int) s;
            }
        }
    }
}

关于绘图的注意事项:您永远不想直接在 JFrame 中绘图,因为 JFrame 是复杂的 GUI 组件,它包含、显示和绘制多个组件,并且在其绘制方法中绘制可能会破坏此功能。此外,它没有paintComponent 方法,因此您会丢失自动双缓冲,如果您做过动画,这很重要。而是在 JPanel 的 paintComponent 方法中绘制,并在您的覆盖中调用 super 的方法,以便可以完成内务绘制。

【讨论】:

    【解决方案2】:

    您将覆盖paint(...),而无需调用绘制框架组件的super.paint(g)。如果你先调用它然后画线,你可能只是在组件上画。您的下一个问题将是布局。如果您不使用 GUI 构建器(无论如何我都不会推荐,因为我是一个纯粹主义者;P),您将不得不处理适当的布局,我认为最好不要将行抽屉放在 JFrame 本身中但是在一个 JPanel 中,它将被放入 JFrame 中。我也推荐 GridBagLayout,但你可能会讨厌我,因为它有点复杂。

    如果您使用的是 GUI 构建器...不知道,我从来没有这样做过。

    【讨论】:

      【解决方案3】:

      右侧有一些空间。我想添加一些 JButtons、JLabels 和 JTextFields 以便用户可以输入功能的数据。

      那么在你的框架中,你需要在框架中添加两个单独的面板:

      1. 您进行自定义绘画的第一个面板。您为这幅画覆盖 paintComponent(..)

      2. 第二个面板将包含您的组件

      所以基本代码是:

      JFrame frame = new JFrame(...);
      frame.add(new PaintingPanel(), BorderLayout.CENTER);
      frame.add(new ComponentPanel(), BorderLayout.LINE_END);
      

      不要直接在框架上进行自定义绘画。

      阅读 Swing 教程中关于自定义绘画的部分以获取更多信息和工作示例。

      【讨论】:

      • 比我的答案更好,更简洁。 1+
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-09
      相关资源
      最近更新 更多