我是Java新手,我自己学习。我陷入了困境。我创建了一个非常基本的绘图应用程序,但是我的朋友告诉我,因为我把所有东西放在一个* .java文件中,你可以告诉我我是一个初学程序员,因为我不是真的使用面向对象的编程:D所以我决定将我的代码分成各种文件。但现在代码不起作用(显然)。
所以我有Main.java文件为程序创建一个窗口(JFrame),在JFrame内部有两个面板,一个在BorderLayout.WEST上,一个在CENTER中。 .WEST上的那个是SideBar(带按钮等),而.CENTER中的那个是主绘图板:
Main.java文件(公共类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(公共类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) {
}
}
}
后来有sidebar,它位于menuSideBar.java文件(公共类menuSideBar)中,这个类读入了4个其他类(我想添加4个不同的菜单,这里我只展示一个例子):< / p>
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文件(公共类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();
}
}
}
}
现在,当我执行代码时,所有内容都顺利加载,我可以看到所有面板和内部的所有组件,但是当我单击按钮时没有任何反应。我猜它与继承有关,或者实际上我有几个问题:
谢谢!很抱歉,如果这对您来说显而易见,但书籍或教程中的所有示例都有非常简短的继承示例和非常简单的示例,并且我无法将这些简单示例转移到我的代码中。谢谢!
答案 0 :(得分:2)
您的主要问题是,当您只需要并且应该有一个时,您正在创建两个Paint对象。要自行检查,请在此页面中搜索new Paint()
的次数。你应该只在代码中看到它一次,并且你看到它两次。
为什么这很重要?一个Paint对象显示在GUI中,另一个不显示,但在ActionListener中按下按钮时会调用其方法。在未显示的对象上调用方法不会转换为显示的对象中的可见响应。
错误的一个简单解决方案是让您的绘图变量保持静态并在任何地方共享它。这是错误的,因为你失去了OOP的好处并增加了bug的风险。更好的方法是将可视化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()
。