Java,在特定的 JPanel 上绘制
Java, draw on a specific JPanel
我正在开发一个程序,该程序根据用户提供的输入绘制线性函数。
我设法创建了一个绘制 "line" (很多点)的方法。
如您在屏幕截图中所见,右侧有一些 space。我想添加一些 JButtons、JLabels 和 JTextFields,以便用户可以输入函数的数据。
Screenshot of the program
但是如果我添加一些 JButton 或一些 JLabel,它们将不会显示在右侧。谁能向我解释这种行为的原因?我将上传没有 JButtons 版本的源代码。
谢谢大家的帮助!
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();
}
}
您正在覆盖 paint(...)
,而没有调用绘制框架组件的 super.paint(g)
。如果你先调用它然后再画线,你可能只是在组件上画画。您的下一个问题将是布局。如果您没有使用 GUI 生成器(无论如何我都不会推荐,因为我是纯粹主义者;P),您将不得不处理适当的布局,我认为最好不要将抽屉放在 JFrame 本身中但是在将放在 JFrame 中的 JPanel 中。我还推荐 GridBagLayout,但你可能会因此讨厌我,因为它有点复杂。
如果您使用的是 GUI 生成器...不知道,我从来没有用过。
如果您想在右侧添加按钮,您将需要了解和使用布局管理器。一个关键概念是,您可以通过嵌套 JPanel 来有效地 nest 布局,每个 JPanel 使用自己的布局。例如,如果我们在 JPanel 中绘制(建议这样做而不是直接在 JFrame 中绘制,我们可以将此 JPanel 放置在另一个 JPanel 中,该 JPanel 在 BorderLayOut.CENTER 位置使用 BorderLayout。然后我们可以添加另一个使用 GridLayout 将按钮添加到此外部 JPanel 右侧的 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 组件,可以容纳、显示和绘制多个组件,并且在其 paint 方法中绘图有可能会破坏此功能。而且它没有 paintComponent 方法,所以你失去了自动双缓冲,这在你做动画时很重要。取而代之的是在 JPanel 的 paintComponent 方法中进行绘制,并在您的重写中调用 super 的方法,以便可以完成内务处理绘制。
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.
那么在您的框架中,您需要向框架添加两个单独的面板:
您进行自定义绘画的第一个面板。您为这幅画覆盖 paintComponent(..)
。
第二个面板将包含您的组件
所以基本代码是:
JFrame frame = new JFrame(...);
frame.add(new PaintingPanel(), BorderLayout.CENTER);
frame.add(new ComponentPanel(), BorderLayout.LINE_END);
不要直接在框架上自定义绘画。
阅读 Swing 教程中有关自定义绘画的部分,了解更多信息和工作示例。
我正在开发一个程序,该程序根据用户提供的输入绘制线性函数。 我设法创建了一个绘制 "line" (很多点)的方法。
如您在屏幕截图中所见,右侧有一些 space。我想添加一些 JButtons、JLabels 和 JTextFields,以便用户可以输入函数的数据。
Screenshot of the program
但是如果我添加一些 JButton 或一些 JLabel,它们将不会显示在右侧。谁能向我解释这种行为的原因?我将上传没有 JButtons 版本的源代码。 谢谢大家的帮助!
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();
}
}
您正在覆盖 paint(...)
,而没有调用绘制框架组件的 super.paint(g)
。如果你先调用它然后再画线,你可能只是在组件上画画。您的下一个问题将是布局。如果您没有使用 GUI 生成器(无论如何我都不会推荐,因为我是纯粹主义者;P),您将不得不处理适当的布局,我认为最好不要将抽屉放在 JFrame 本身中但是在将放在 JFrame 中的 JPanel 中。我还推荐 GridBagLayout,但你可能会因此讨厌我,因为它有点复杂。
如果您使用的是 GUI 生成器...不知道,我从来没有用过。
如果您想在右侧添加按钮,您将需要了解和使用布局管理器。一个关键概念是,您可以通过嵌套 JPanel 来有效地 nest 布局,每个 JPanel 使用自己的布局。例如,如果我们在 JPanel 中绘制(建议这样做而不是直接在 JFrame 中绘制,我们可以将此 JPanel 放置在另一个 JPanel 中,该 JPanel 在 BorderLayOut.CENTER 位置使用 BorderLayout。然后我们可以添加另一个使用 GridLayout 将按钮添加到此外部 JPanel 右侧的 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 组件,可以容纳、显示和绘制多个组件,并且在其 paint 方法中绘图有可能会破坏此功能。而且它没有 paintComponent 方法,所以你失去了自动双缓冲,这在你做动画时很重要。取而代之的是在 JPanel 的 paintComponent 方法中进行绘制,并在您的重写中调用 super 的方法,以便可以完成内务处理绘制。
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.
那么在您的框架中,您需要向框架添加两个单独的面板:
您进行自定义绘画的第一个面板。您为这幅画覆盖
paintComponent(..)
。第二个面板将包含您的组件
所以基本代码是:
JFrame frame = new JFrame(...);
frame.add(new PaintingPanel(), BorderLayout.CENTER);
frame.add(new ComponentPanel(), BorderLayout.LINE_END);
不要直接在框架上自定义绘画。
阅读 Swing 教程中有关自定义绘画的部分,了解更多信息和工作示例。