简体   繁体   English

Java,使用特定的JPanel

[英]Java, draw on a specific JPanel

I'm working on a program which is drawing a linear function based on the inputs given by the user. 我正在开发一个程序,该程序根据用户给出的输入来绘制线性函数。 I managed to create a method which draws the "line" (many points). 我设法创建了一种绘制“线”(很多点)的方法。

As you see in the screenshot, there is some space on the right hand side. 如您在屏幕快照中所见,右侧有一些空间。 I would like to add some JButtons, JLabels and JTextFields in order that the user can input the data for the function. 我想添加一些JButton,JLabels和JTextField,以便用户可以输入该函数的数据。

Screenshot of the program 程序截图

But if I add some JButtons or some JLabels, they won't display on the right hand side. 但是,如果我添加一些JButton或一些JLabel,它们将不会显示在右侧。 Can anybody explain me the reason for this behavior? 谁能解释这个现象的原因? I will upload the sourcecode of the version without the JButtons. 我将上传不带JButton的版本的源代码。 Thank you guys for your help! 谢谢你们的帮助!

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


    }

}

If you want to add buttons to the right, you're going to want to learn about and use the layout managers. 如果要在右侧添加按钮,则需要了解和使用布局管理器。 A key concept is that you can effectively nest layouts by nesting JPanels, each one using its own layout. 一个关键概念是,您可以通过嵌套JPanels来有效地嵌套布局,每个JPanel都使用其自己的布局。 For instance, if we did our drawing in a JPanel (and this is recommended to do rather than drawing directly in a JFrame, we can place this JPanel in another JPanel that uses BorderLayout in the BorderLayOut.CENTER position. We can then add another JPanel that uses GridLayout to add buttons to the right side of this outer JPanel. 例如,如果我们在一个JPanel中进行绘制(建议这样做而不是直接在JFrame中进行绘制,则可以将该JPanel放置在另一个使用BorderLayOut.CENTER位置的BorderLayout的JPanel中。然后可以添加另一个JPanel使用GridLayout在该外部JPanel的右侧添加按钮。

Perhaps it's better to just show an example: 也许最好举个例子:

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

A note on drawing: you never want to draw directly in the JFrame as JFrames are complex GUI components that hold, display and paint multiple components, and drawing in its paint method risks messing up this functionality. 关于绘图的注意事项:永远不要直接在JFrame中绘图,因为JFrame是包含,显示和绘制多个组件的复杂GUI组件,以其绘制方法进行绘制可能会混淆此功能。 Also it doesn't have a paintComponent method and so you lose automatic double buffering which is important if you ever do animation. 而且它没有paintComponent方法,因此您会丢失自动双缓冲,这对您制作动画非常重要。 Instead draw in the paintComponent method of a JPanel and do call the super's method in your override so that housekeeping painting can be done. 取而代之的是绘制JPanel的paintComponent方法,并在您的重写中调用super的方法,从而可以完成内部管理绘画。

You are overriding paint(...) without a call to super.paint(g) where the components of the frame are drawn. 您要覆盖paint(...)而无需调用绘制框架组件的super.paint(g) And if you call it first and draw your lines afterwards, you may just draw over the components. 而且,如果先调用它,然后再画线,则可以绘制组件。 Your next problem will be the layout. 您的下一个问题将是布局。 If you are not using a GUI builder (which I wouldn't recommend anyway because I'm a purist ;P), you will have to deal with an appropiate layout and I think it's advisable to put the line drawer not in the JFrame itself but in a JPanel which will be put in the JFrame. 如果您没有使用GUI生成器(由于我是纯粹主义者,我还是不建议这样做),那么您将不得不处理适当的布局,并且我建议不要将行抽屉放在JFrame本身中但在将放置在JFrame中的JPanel中。 I also recommend the GridBagLayout, but you will probably hate me for that as it is a little bit sophisticated. 我还建议使用GridBagLayout,但是您可能会讨厌它,因为它有点复杂。

And if you are using a GUI builder... no idea, I never did. 而且,如果您使用的是GUI构建器...不知道,我从没做过。

there is some space on the right hand side. 右侧有一些空间。 I would like to add some JButtons, JLabels and JTextFields in order that the user can input the data for the funktion. 我想添加一些JButton,JLabels和JTextFields,以便用户可以输入功能的数据。

So then in you your frame you need to add two separate panels to the frame: 因此,在您的框架中,您需要向框架添加两个单独的面板:

  1. the first panel where you do the custom painting. 进行自定义绘画的第一个面板。 You override paintComponent(..) for this painting. 您可以为此绘画覆盖paintComponent(..)

  2. the second panel will contain your components 第二个面板将包含您的组件

So the basic code would be: 因此,基本代码为:

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

Don't do custom painting directly on the frame. 不要直接在框架上进行自定义绘画。

Read the section from the Swing tutorial on Custom Painting for more information and working examples. 阅读有关定制绘画的Swing教程中的部分,以获取更多信息和工作示例。

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

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