Drawing tree not visible; maybe layout issue

落爺英雄遲暮 提交于 2020-01-07 00:33:32

问题


I want to display a tree. But the tree does not appear. What is the problem?

Main:

package scanner_parser;
public class Main {
    public static void main(String[] args) {
        Oberflaeche gui = new Oberflaeche();
        gui.setVisible(true);
    }
}

GUI:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;
import javax.swing.*;

public class Oberflaeche extends JFrame implements ActionListener {

    private JPanel cp, top, bottom;
    private JTextField eingabefeld = new JTextField();
    private JButton button = new JButton("Darstellen");
    private JMenuBar menubar = new JMenuBar();
    private JMenu menu;
    private JMenuItem anleitung, beenden, bEins, bZwei, bDrei, bVier;
    private Baum baum = new Baum();

    public Oberflaeche() {
        this.setTitle("Funktionsparser");
        this.setSize(900, 700);
        this.setLocation(300, 100);
        this.setResizable(true);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        initMenu();

        cp = (JPanel) this.getContentPane();
        cp.setLayout(new BorderLayout(2, 1));
        top = new JPanel();
        top.setLayout(null);
        top.setBounds(0, 0, getWidth(), 50);
        top.setBackground(Color.white);

        bottom = new JPanel();
        bottom.setBounds(0, 50, getWidth(), getHeight() - 50);
        bottom.setBackground(Color.white);

        eingabefeld.setBounds(10, 10, getWidth() - 120, 30);
        button.setBounds(getWidth() - 110, 10, 100, 30);
        button.addActionListener(this);

        top.add(button);
        top.add(eingabefeld);
        cp.add(top);
        cp.add(bottom);
    }

    // Initialise Menu

    private void initMenu() {
        menu = new JMenu("Datei");
        anleitung = new JMenuItem("Anleitung");
        anleitung.addActionListener(this);

        menu.add(anleitung);
        beenden = new JMenuItem("Beenden");
        beenden.addActionListener(this);

        menu.add(beenden);
        menubar.add(menu);

        menu = new JMenu("Beispiele");

       // Load some example functions into the textfield

        bEins = new JMenuItem("<html>3 * x</html>");
        bEins.addActionListener(this);
        menu.add(bEins);

        bZwei = new JMenuItem("<html>3 * x<sup>2</sup></html>");
        bZwei.addActionListener(this);
        menu.add(bZwei);

        bDrei = new JMenuItem("<html>3 * ( x<sup>2</sup> + 1 )</html>");
        bDrei.addActionListener(this);
        menu.add(bDrei);

        bVier = new JMenuItem("<html>3 * ( x<sup>2</sup> + x<sup>4</sup> + 1 )</html>");
        bVier.addActionListener(this);
        menu.add(bVier);

        menubar.add(menu);

        this.setJMenuBar(menubar);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        Object s = e.getSource();

        if (s == anleitung) {

        }

       // This should add the tree (baum) but it does not appear.


        if (s == button) {
            FuncParser.theParser().parse(eingabefeld.getText());
            FuncParser.theParser().getWurzel().print();
            bottom.add(baum);
        }
        if (s == beenden) {
            System.exit(0);
        }
        if (s == bEins) {
            eingabefeld.setText("3*x");
        }
        if (s == bZwei) {
            eingabefeld.setText("3*x^2");
        }
        if (s == bDrei) {
            eingabefeld.setText("3*(x^2+1)");
        }
        if (s == bVier) {
            eingabefeld.setText("3*(x^2+x^4+1)");
        }
    }
}

The Tree class:

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

public class Baum extends JPanel {

    private final int radius = 20;
    private final int paddingY = 75;

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        System.out.println("test");
        displayBaum(g, FuncParser.theParser().getWurzel(), getWidth() / 2, 100, 20 + getWidth() / 4);
    }

    private void displayBaum(Graphics g, Knoten k, int x, int y, int paddingX) {
        g.drawOval(x - radius, y - radius, 2 * radius, 2 * radius);
        g.drawString(k.getDaten(), x - 4, y + 4);

        if (k.getLinks() != null) {
            displayKante(g, x - paddingX, y + paddingY, x, y);
            displayBaum(g, k.getLinks(), x - paddingX, y + paddingY, 10 + paddingX / 2);
            displayKante(g, x + paddingX, y + paddingY, x, y);
            displayBaum(g, k.getLinks(), x + paddingX, y + paddingY, 10 + paddingX / 2);
        }
    }

    private void displayKante(Graphics g, int x1, int y1, int x2, int y2) {
        double d = Math.sqrt(paddingY * paddingY + (x2 - x1) * (x2 - x1));
        int x11 = (int) (x1 - radius * (x1 - x2) / d);
        int y11 = (int) (y1 - radius * (y1 - y2) / d);
        int x21 = (int) (x2 + radius * (x1 - x2) / d);
        int y21 = (int) (y2 + radius * (y1 - y2) / d);
        g.drawLine(x11, y11, x21, y21);
    }
}

The text "test" appear in the console every time I scale the window. This means the function is called but the tree does not appear on the content pane. Maybe its underneath something? I don't now why. Please help if you have an idea.


回答1:


Reducing your fragments to a compilable state, I get the following results. In particular,

  • Don't use a null layout; the example uses the default BorderLayout for JFrame and FlowLayout for Panel.

  • Use the JTextField constructor that lets you specify the field's width in columns.

  • Override getPreferredSize() to establish the drawing area's initial geometry, and draw relative to its current dimensions.

  • Construct and manipulate Swing GUI objects only on the event dispatch thread.

  • Use equals() in preference to == in your ActionListener.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;

/**
 * @See https://stackoverflow.com/a/38215252/230513
 */
public class Main {

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            Oberflaeche gui = new Oberflaeche();
            gui.setVisible(true);
        });
    }

    private static class Baum extends JPanel {

        private final int radius = 20;
        private final int paddingY = 75;

        @Override
        public void paintComponent(Graphics g) {
            super.paintComponent(g);
            g.drawString("Hello", 16, 16);
            displayKante(g, 0, 0, getWidth(), getHeight());
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(329, 240);
        }

        private void displayKante(Graphics g, int x1, int y1, int x2, int y2) {
            double d = Math.sqrt(paddingY * paddingY + (x2 - x1) * (x2 - x1));
            int x11 = (int) (x1 - radius * (x1 - x2) / d);
            int y11 = (int) (y1 - radius * (y1 - y2) / d);
            int x21 = (int) (x2 + radius * (x1 - x2) / d);
            int y21 = (int) (y2 + radius * (y1 - y2) / d);
            g.drawLine(x11, y11, x21, y21);
        }
    }

    private static class Oberflaeche extends JFrame implements ActionListener {

        private JPanel top, bottom;
        private JTextField eingabefeld = new JTextField(20);
        private JButton button = new JButton("Darstellen");
        private JMenuBar menubar = new JMenuBar();
        private JMenu menu;
        private JMenuItem anleitung, beenden, bEins, bZwei, bDrei, bVier;
        private Baum baum = new Baum();

        public Oberflaeche() {
            this.setDefaultCloseOperation(EXIT_ON_CLOSE);
            this.setTitle("Funktionsparser");
            initMenu();
            top = new JPanel();
            top.setBackground(Color.white);
            top.add(button);
            top.add(eingabefeld);
            button.addActionListener(this);
            bottom = new JPanel();
            bottom.setBackground(Color.white);
            bottom.add(new JLabel("Label text."));
            this.add(top, BorderLayout.NORTH);
            this.add(baum);
            this.add(bottom, BorderLayout.SOUTH);
            this.pack();
            this.setLocationRelativeTo(null);
        }

        // Initialise Menu
        private void initMenu() {
            menu = new JMenu("Datei");
            anleitung = new JMenuItem("Anleitung");
            anleitung.addActionListener(this);
            menu.add(anleitung);
            beenden = new JMenuItem("Beenden");
            beenden.addActionListener(this);
            menu.add(beenden);
            menubar.add(menu);
            menu = new JMenu("Beispiele");
            // Load some example functions into the textfield
            bEins = new JMenuItem("<html>3 * x</html>");
            bEins.addActionListener(this);
            menu.add(bEins);
            bZwei = new JMenuItem("<html>3 * x<sup>2</sup></html>");
            bZwei.addActionListener(this);
            menu.add(bZwei);
            bDrei = new JMenuItem("<html>3 * ( x<sup>2</sup> + 1 )</html>");
            bDrei.addActionListener(this);
            menu.add(bDrei);
            bVier = new JMenuItem("<html>3 * ( x<sup>2</sup> + x<sup>4</sup> + 1 )</html>");
            bVier.addActionListener(this);
            menu.add(bVier);
            menubar.add(menu);
            this.setJMenuBar(menubar);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            Object s = e.getSource();
            if (s == anleitung) {
                System.out.println(anleitung);
            }
            if (s == button) {
                System.out.println(button);
            }
            if (s == beenden) {
                System.exit(0);
            }
            if (s == bEins) {
                eingabefeld.setText("3*x");
            }
            if (s == bZwei) {
                eingabefeld.setText("3*x^2");
            }
            if (s == bDrei) {
                eingabefeld.setText("3*(x^2+1)");
            }
            if (s == bVier) {
                eingabefeld.setText("3*(x^2+x^4+1)");
            }
        }
    }
}



回答2:


You are adding both panels to the center of the content pane, cp, and you never add baum. Use constraints on the panels like this:

cp.add(top, BorderLayout.NORTH);
cp.add(baum, BorderLayout.CENTER);
cp.add(bottom, BorderLayout.SOUTH);


来源:https://stackoverflow.com/questions/38209846/drawing-tree-not-visible-maybe-layout-issue

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!