简体   繁体   中英

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.

Screenshot of the program

But if I add some JButtons or some JLabels, they won't display on the right hand side. Can anybody explain me the reason for this behavior? I will upload the sourcecode of the version without the JButtons. 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. 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.

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. Also it doesn't have a paintComponent method and so you lose automatic double buffering which is important if you ever do animation. 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.

You are overriding paint(...) without a call to super.paint(g) where the components of the frame are drawn. 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. I also recommend the GridBagLayout, but you will probably hate me for that as it is a little bit sophisticated.

And if you are using a GUI builder... no idea, I never did.

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.

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.

  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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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