问题
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 defaultBorderLayout
forJFrame
andFlowLayout
forPanel
.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 yourActionListener
.
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