gpt4 book ai didi

Java:Paint应用程序,代码不起作用,我做错了什么?

转载 作者:行者123 更新时间:2023-11-30 02:44:40 25 4
gpt4 key购买 nike

我是 Java 新手,正在自学。我在这一点上陷入困​​境。我创建了一个非常基本的绘图应用程序,但我的 friend 告诉我,当我将所有内容都放在一个 *.java 文件中时,您可以看出我是一名初级程序员,因为我并没有真正使用面向对象编程:D 所以我决定将我的代码分成不同的文件。但现在代码不起作用(显然)。

所以我有 Main.java 文件,它为程序 (JFrame) 创建一个窗口,在该 JFrame 内部有 2 个面板,一个位于 BorderLayout.WEST,第二个位于 CENTER。 .WEST 上的那个是侧栏(带有按钮等),.CENTER 上的那个是主绘图板:

Main.java 文件(公共(public)类 Main):

import java.awt.*;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import javax.swing.*;

public class Main {

private Paint myPaint;
private menuSideBar sidePanel;

Main(){

JFrame ramka = new JFrame("Paint Application");

sidePanel = new menuSideBar(); //this is the sidebar
myPaint = new Paint(); // this is the drawing board

ramka.getContentPane().add(sidePanel, BorderLayout.WEST);
ramka.getContentPane().add(myPaint, BorderLayout.CENTER);
ListenForWindow lForWindow = new ListenForWindow();
ramka.addWindowListener(lForWindow);
ramka.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
ramka.setSize(1400, 800);
ramka.setLocationRelativeTo(null);
ramka.setVisible(true);

}

private class ListenForWindow implements WindowListener{

public void windowOpened(WindowEvent e) {
}

public void windowClosing(WindowEvent e) {
int closing = JOptionPane.showConfirmDialog(null, "Exit program?", "Exit", JOptionPane.YES_NO_OPTION);
if (closing == JOptionPane.YES_OPTION){
System.exit(0);
}
}

public void windowClosed(WindowEvent e) {
}

public void windowIconified(WindowEvent e) {
}

public void windowDeiconified(WindowEvent e) {
}

public void windowActivated(WindowEvent e) {
}

public void windowDeactivated(WindowEvent e) {
}

}


public static void main(String[] args){
new Main();
}

}

然后我就有了画板,位于文件 Paint.java(公共(public)类 Paint)中:

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import javax.swing.*;

public class Paint extends JComponent {

private static final long serialVersionUID = 1L;
private BufferedImage bimage;
private Graphics2D g2;
private int whichShape;
private int oldX, oldY, newX, newY;
private int w, h;
private Color cColor;

Paint() {


ListenForMouse lForMouse = new ListenForMouse();
this.addMouseListener(lForMouse);
this.addMouseMotionListener(lForMouse);

}

public void paintComponent(Graphics g){


if (bimage == null){
bimage = new BufferedImage(getSize().width, getSize().height, BufferedImage.TYPE_INT_ARGB);
g2 = (Graphics2D) bimage.getGraphics();
g2.setBackground(Color.WHITE);
g2.setColor(Color.BLACK);
clear();
}

g.drawImage(bimage, 0, 0, null);
}

public void clear(){
g2.clearRect(0, 0, getSize().width, getSize().height);
repaint();
}


public void draw(){

w = newX - oldX;
h = newY - oldY;

if (w<0){
w = w * (-1);
}
if (h<0){
h = h * (-1);
}


switch (whichShape) {

case 1:
check();
g2.drawRect(oldX, oldY, w, h);
repaint();
break;
case 2:
check();
g2.drawRoundRect(oldX, oldY, w, h, 40, 40);
repaint();
break;
case 3:
check();
g2.drawOval(oldX, oldY, w, h);
repaint();
break;
case 4:
check();
g2.fillRect(oldX, oldY, w, h);
repaint();
break;
case 5:
check();
g2.fillRoundRect(oldX, oldY, w, h, 20, 20);
repaint();
break;
case 6:
check();
g2.fillOval(oldX, oldY, w, h);
repaint();
break;
}
}



public void rectangle(){

whichShape = 1;

}

public void roundedrectangle(){
whichShape = 2;
}

public void oval(){
whichShape = 3;
}

public void filledrectangle(){
whichShape = 4;
}

public void filledroundedrectangle(){
whichShape = 5;
}

public void filledoval(){
whichShape = 6;
}

public void colorChooser(){
cColor = JColorChooser.showDialog(null, "Choose color", Color.black);
g2.setColor(cColor);
}


public void check(){
if (oldX > newX){
int z;
z = oldX;
oldX = newX;
newX = z;
}
if (oldY > newY){
int z;
z = oldY;
oldY = newY;
newY = z;
}
}



public class ListenForMouse implements MouseListener, MouseMotionListener{

public void mouseDragged(MouseEvent e) {

}

public void mouseMoved(MouseEvent e) {
}

public void mouseClicked(MouseEvent e) {
}

public void mousePressed(MouseEvent e) {

if (whichShape == 1 || whichShape == 2 || whichShape == 3 || whichShape == 4 || whichShape == 5 || whichShape == 6){
oldX = e.getX();
oldY = e.getY();
}

}

public void mouseReleased(MouseEvent e) {

if (whichShape == 1 || whichShape == 2 || whichShape == 3 || whichShape == 4 || whichShape == 5 || whichShape == 6){
newX = e.getX();
newY = e.getY();
draw();
}

}

public void mouseEntered(MouseEvent e) {
}

public void mouseExited(MouseEvent e) {
}

}

}

后面还有侧边栏,它在menuSideBar.java文件中(公共(public)类menuSideBar),这个类读取了另外4个类(我要添加4个不同的菜单,这里只展示一个例子):

import javax.swing.*;

public class menuSideBar extends JPanel {

private static final long serialVersionUID = 1L;
sideBar1 sb1;
//sideBar2 sb2;
//sideBar3 sb3;
//sideBar4 sb4;

menuSideBar(){


this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

sb1 = new sideBar1();
//sb2 = new sideBar2();
//sb3 = new sideBar3();
//sb4 = new sideBar4();

this.add(sb1);
//this.add(sb2);
//this.add(sb3);
//this.add(sb4);


}
}

这个 sideBar1.java 文件(公共(public)类 sideBar1)包含 JButtons,其中 ActionListeners 引用 Paint.java 文件中的方法:

import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


public class sideBar1 extends JPanel {

private static final long serialVersionUID = 1L;
Paint myPaint;

JButton pencilBut, brushBtn, bckpaintBtn, eraserBtn, textBtn, rectBtn, roundedrectBtn, ovalBtn, frectBtn, fovalBtn, froundedrectBtn, lineBtn;

sideBar1(){


Border border = BorderFactory.createTitledBorder("Paint");
this.setBorder(border);
this.setLayout(new GridLayout(0,3));
myPaint = new Paint();

ListenForButton lForButton = new ListenForButton();

pencilBut = new JButton("pencil");
pencilBut.addActionListener(lForButton);
brushBtn = new JButton("brush");
brushBtn.addActionListener(lForButton);
bckpaintBtn = new JButton("background paint");
bckpaintBtn.addActionListener(lForButton);
eraserBtn = new JButton("eraser");
eraserBtn.setIcon(icon_eraser);
eraserBtn.addActionListener(lForButton);
textBtn = new JButton("text");
textBtn.addActionListener(lForButton);
lineBtn = new JButton("line");
lineBtn.addActionListener(lForButton);
rectBtn = new JButton("rectangle");
rectBtn.addActionListener(lForButton);
roundedrectBtn = new JButton("rounded rectangle");
roundedrectBtn.addActionListener(lForButton);
ovalBtn = new JButton("oval");
ovalBtn.addActionListener(lForButton);
frectBtn = new JButton("filled rectangle");
frectBtn.addActionListener(lForButton);
froundedrectBtn = new JButton("filled rounded rectangle");
froundedrectBtn.addActionListener(lForButton);
fovalBtn = new JButton("filled oval");
fovalBtn.addActionListener(lForButton);



this.add(pencilBut);
this.add(brushBtn);
this.add(bckpaintBtn);
this.add(eraserBtn);
this.add(textBtn);
this.add(lineBtn);
this.add(rectBtn);
this.add(roundedrectBtn);
this.add(ovalBtn);
this.add(frectBtn);
this.add(froundedrectBtn);
this.add(fovalBtn);





}

public class ListenForButton implements ActionListener{

@Override
public void actionPerformed(ActionEvent e) {


if (e.getSource() == brushBtn){

} else if (e.getSource() == bckpaintBtn){

} else if (e.getSource() == eraserBtn){

} else if (e.getSource() == textBtn){

} else if (e.getSource() == lineBtn){

} else if (e.getSource() == rectBtn){
System.out.println("rectangle");
myPaint.rectangle();
} else if (e.getSource() == roundedrectBtn){
myPaint.roundedrectangle();
} else if (e.getSource() == ovalBtn){
myPaint.oval();
} else if (e.getSource() == frectBtn){
myPaint.filledrectangle();
} else if (e.getSource() == froundedrectBtn){
myPaint.filledroundedrectangle();
} else if (e.getSource() == fovalBtn){
myPaint.filledoval();
}


}

}


}

现在,当我执行代码时,所有内容都会顺利加载,我可以看到所有面板和内部的所有组件,但是当我单击按钮时,什么也没有发生。我猜这与继承有关,或者实际上我有几个问题:

  1. 我对我 friend 的理解正确吗?我是否应该将代码分成不同的 *.java 文件,并将每个类放在同一个包中的不同文件中?或者我应该将这些不同的类包含在一个 *.java 文件中? (如果后一个选项可以,有人可以至少修改我的代码的一个片段,这样我就知道如何正确合并继承吗?,一些类扩展了 JPanels 和 JComponents,我读到你不应该混淆使用模型扩展 JPanel 等( View )(?)
  2. 是否可以读取位于另一个文件 menuSideBar.java 中的 Main.java 文件 JPanel,然后读取位于 sideBar1.java 内的 menuSideBar.java 面板?或者我应该定义哪个面板进入主类中的哪个面板?
  3. 为什么 Paint.java 没有读取 sideBar1.java 的 JButton 的 ActionListener?我做错了什么?

谢谢!抱歉,如果这对您来说似乎很明显,但是书籍或教程中的所有示例都有非常简短的继承示例和非常简单的示例,并且不知何故我无法将这些简单的示例转移到我的代码中。谢谢!

最佳答案

您的主要问题是,当您只需要并且应该有一个 Paint 对象时,您正在创建两个 Paint 对象。要亲自检查这一点,请搜索此页面以了解您看到 new Paint() 的次数。你应该只在代码中看到它一次,而你却看到了它两次。

为什么这很重要?一个 Paint 对象显示在 GUI 中,另一个则不显示,但在 ActionListener 中按下按钮时会调用其方法。在非显示对象上调用方法不会转换为显示对象中的可见响应。

一个简单但错误的解决方案是使您的绘图变量静态并在任何地方共享它。这是错误的,因为您会失去 OOP 的好处并增加错误的风险。更好的方法是将可视化 Paint 对象的引用传递到需要的 ActionListener 中,以便仅创建一个 Paint 对象,并在监听器中调用与显示的同一 Paint 对象上的方法。

更具体,更改此:

sidePanel = new menuSideBar(); //this is the sidebar
myPaint = new Paint(); // this is the drawing board

对此:

myPaint = new Paint(); // call this first
sidePanel = new menuSideBar(myPaint); // and pass it in

在sideBar构造函数中(该类应重命名为SideBar),使用参数:

public sideBar(Paint myPaint) {
this.myPaint = myPaint;
// .... all other constructor code
}

并从 sideBar 中删除 new Paint()

关于Java:Paint应用程序,代码不起作用,我做错了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40556548/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com