Java 我的方法被调用了,但它没有画线
下面是我画一个游泳池的代码,同时计算它的体积 所讨论的方法是paintswimingpool(),当stateChanged()监听器方法调用它时,它可以正常工作。然而,问题是我想在启动程序时绘制矩形。我添加了一些控制台消息来帮助调试,它告诉我该方法是从createGUI()方法正确调用的。但是为什么paintswimingpool()不在面板上绘制任何东西呢?对不起,我花了很长时间来解决这个问题,但没有找到解决的地方 提前感谢您的指点Java 我的方法被调用了,但它没有画线,java,swing,Java,Swing,下面是我画一个游泳池的代码,同时计算它的体积 所讨论的方法是paintswimingpool(),当stateChanged()监听器方法调用它时,它可以正常工作。然而,问题是我想在启动程序时绘制矩形。我添加了一些控制台消息来帮助调试,它告诉我该方法是从createGUI()方法正确调用的。但是为什么paintswimingpool()不在面板上绘制任何东西呢?对不起,我花了很长时间来解决这个问题,但没有找到解决的地方 提前感谢您的指点 import java.awt.Color; import
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Frame;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
public class SwimingPoolCalculator implements ChangeListener {
private JFrame frame;
private JPanel primaryJPanel, drawingJPanel;
private JLabel deepJLabel, shallowJLabel;
private JSlider deepJSlider, shallJSlider;
private JTextField resultTextField;
final private int xPos = 20;
final private int yPos = 20;
final private int swimmingPoolLength = 200;
final private int swimmingPoolWidth = 50;
public static void main(String[] args) {
SwimingPoolCalculator swimingPoolCalculator = new SwimingPoolCalculator();
swimingPoolCalculator.createGUI();
}
private void createGUI(){
frame = new JFrame("Swiming Pool Calculator");
primaryJPanel = new JPanel();
primaryJPanel.setPreferredSize(new Dimension(250, 500));
drawingJPanel = new JPanel();
drawingJPanel.setPreferredSize(new Dimension(250, 300));
drawingJPanel.setBackground(Color.yellow);
shallowJLabel = new JLabel("S End");
deepJLabel = new JLabel("D End");
shallJSlider = new JSlider(JSlider.HORIZONTAL, 10, 100, 10);
deepJSlider = new JSlider(JSlider.HORIZONTAL, 50, 200, 100);
shallJSlider.addChangeListener(this);
deepJSlider.addChangeListener(this);
resultTextField = new JTextField(15);
primaryJPanel.add(drawingJPanel);
primaryJPanel.add(shallowJLabel);
primaryJPanel.add(shallJSlider);
primaryJPanel.add(deepJLabel);
primaryJPanel.add(deepJSlider);
primaryJPanel.add(resultTextField);
frame.getContentPane().add(primaryJPanel);
frame.pack();
frame.setVisible(true);
// why the first call does not draw any line?
paintSwimmingPool(deepJSlider.getValue(), shallJSlider.getValue());
}
private void paintSwimmingPool(int deepEnd, int shallowEnd){
Graphics drawingBoard = drawingJPanel.getGraphics();
drawingBoard.setColor(Color.yellow);
drawingBoard.fillRect(0, 0, 250, 250);
drawingBoard.setColor(Color.black);
drawingBoard.drawLine(xPos, yPos, xPos + swimmingPoolLength, yPos); // the top line
drawingBoard.drawLine(xPos, yPos, xPos, yPos + deepEnd); // the left line
drawingBoard.drawLine(xPos + swimmingPoolLength, yPos, xPos + swimmingPoolLength, yPos + shallowEnd); // the right line
drawingBoard.drawLine(xPos, yPos + deepEnd, xPos + swimmingPoolLength, yPos + shallowEnd); // the bottom line
}
private void calculateVolume(double averageDepth){
int swimmingPoolVolume = (int)(averageDepth * swimmingPoolLength * swimmingPoolWidth);
resultTextField.setText("Volume: " + swimmingPoolVolume);
}
@Override
public void stateChanged(ChangeEvent e) {
int shallowEnd = shallJSlider.getValue();
int deepEnd = deepJSlider.getValue();
double averageDepth = (shallowEnd + deepEnd) / 2;
paintSwimmingPool(deepEnd, shallowEnd);
calculateVolume(averageDepth);
}
}
Swing可能是在您在JPanel上绘制后重新绘制的。Swing可以在任何时候,出于任何原因重新绘制组件。因此,您不应该使用
getGraphics
相反,您需要创建自己的组件类(扩展现有组件,例如JPanel
),并覆盖paintComponent
有关更多详细信息,请参阅。您不能这样绘制,正确的方法是
- 重写JPanel子类中的paintComponent()方法,并改用Graphics参数李>
- 调用repaint()来触发重新绘制,而不是paintswimingpool()方法
- 将参数(如deepEnd和shallowEnd)移动到字段中,并从paintComponent()方法引用这些参数-我们可以“看到”这些字段的内部类。理想情况下,这些将在一个单独的模型中,由绘图面板和控制代码共享,但是内部类完成了任务
- 看这张照片
public class SwimingPoolCalculator implements ChangeListener {
private JFrame frame;
private JPanel primaryJPanel, drawingJPanel;
private JLabel deepJLabel, shallowJLabel;
private JSlider deepJSlider, shallJSlider;
private JTextField resultTextField;
final private int xPos = 20;
final private int yPos = 20;
final private int swimmingPoolLength = 200;
final private int swimmingPoolWidth = 50;
private int deepEnd; // <== moved to fields
private int shallowEnd; // <== moved to fields
private class InnerDrawingPanel extends JPanel {
@Override
protected void paintComponent(Graphics drawingBoard) {
drawingBoard.setColor(Color.yellow); // <== drawing code now here
drawingBoard.fillRect(0, 0, 250, 250);
drawingBoard.setColor(Color.black);
drawingBoard.drawLine(xPos, yPos, xPos + swimmingPoolLength, yPos); // the top line
drawingBoard.drawLine(xPos, yPos, xPos, yPos + deepEnd); // the left line
drawingBoard.drawLine(xPos + swimmingPoolLength, yPos, xPos + swimmingPoolLength, yPos + shallowEnd); // the right line
drawingBoard.drawLine(xPos, yPos + deepEnd, xPos + swimmingPoolLength, yPos + shallowEnd); // the bottom line
}
}
public static void main(String[] args) {
SwimingPoolCalculator swimingPoolCalculator = new SwimingPoolCalculator();
swimingPoolCalculator.createGUI();
}
private void createGUI(){
frame = new JFrame("Swiming Pool Calculator");
primaryJPanel = new JPanel();
primaryJPanel.setPreferredSize(new Dimension(250, 500));
drawingJPanel = new InnerDrawingPanel(); // <== use inner class
drawingJPanel.setPreferredSize(new Dimension(250, 300));
drawingJPanel.setBackground(Color.yellow);
shallowJLabel = new JLabel("S End");
deepJLabel = new JLabel("D End");
shallJSlider = new JSlider(JSlider.HORIZONTAL, 10, 100, 10);
deepJSlider = new JSlider(JSlider.HORIZONTAL, 50, 200, 100);
shallJSlider.addChangeListener(this);
deepJSlider.addChangeListener(this);
resultTextField = new JTextField(15);
primaryJPanel.add(drawingJPanel);
primaryJPanel.add(shallowJLabel);
primaryJPanel.add(shallJSlider);
primaryJPanel.add(deepJLabel);
primaryJPanel.add(deepJSlider);
primaryJPanel.add(resultTextField);
frame.getContentPane().add(primaryJPanel);
frame.pack();
frame.setVisible(true);
// why the first call does not draw any line?
shallowEnd = deepJSlider.getValue(); // <== now update fields
deepEnd = shallJSlider.getValue();
drawingJPanel.repaint(); // <== trigger repaint
}
private void calculateVolume(double averageDepth){
int swimmingPoolVolume = (int)(averageDepth * swimmingPoolLength * swimmingPoolWidth);
resultTextField.setText("Volume: " + swimmingPoolVolume);
}
@Override
public void stateChanged(ChangeEvent e) {
shallowEnd = shallJSlider.getValue(); // <== update fields
deepEnd = deepJSlider.getValue();
double averageDepth = (shallowEnd + deepEnd) / 2;
drawingJPanel.repaint(); // <== trigger repaint
calculateVolume(averageDepth);
}
}
公共类SwimingPoolCalculator实现ChangeListener{
私有JFrame;
private JPanel primaryJPanel,drawingJPanel;
私人JLabel deepJLabel,shallowJLabel;
私人JSlider deepJSlider,shallJSlider;
私有JTextField resultTextField;
最终私有int xPos=20;
最终私有int yPos=20;
最终专用游泳池长度=200;
最终私用游泳池宽度=50;
private int deepEnd;//查看和(cough)super.paintComponent
(cough)g.drawImage(image,0,0,null);
应该是g.drawImage(image,0,0,this)
asJPanel
通过JComponent
实现ImageObserver
接口。如果不处理您创建的图形
上下文(image.getGraphics();
),也可能会出现问题在某些系统上,但这是一个工作流问题。嗨@Adam,但我还有另一个问题。我设置了另一个类并尝试在其中绘制游泳池。但是,我如何将所需的参数(如xPos、YPO)传递给paintComponent(图形g)?我无法使用您上面显示的技术进行计算。您能更具体一点吗?谢谢。我重新修改了我的答案,以向您展示如何使用参数,即不使用参数,而是使用共享状态。理想情况下,这些将在一个由绘图面板和控制代码共享的正式模型中,但我使用的内部类是g完成这项工作。