![](/img/trans.png)
[英]Official Java excercize solution doesn't work… what I am doing wrong?
[英]Java: Paint application, the code doesn't work, what am I doing wrong?
我是Java的新手,我自己學習。 我被困在這一點上。 我創建了一個非常基本的繪畫應用程序,但是我的朋友告訴我,當我將所有內容都放在一個* .java文件中時,由於我沒有真正使用面向對象的編程,因此您可以說我是一名初學者。我決定將代碼分成多個文件。 但是現在代碼不起作用了(顯然)。
所以我有Main.java文件,它為程序(JFrame)創建一個窗口,並且在JFrame的內部有2個面板,一個位於BorderLayout.WEST上,另一個位於CENTER中。 .WEST上的一個是邊欄(帶有按鈕等),. 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) {
}
}
}
稍后有側邊欄,它位於menuSideBar.java文件(公共類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文件(公共類sideBar1)包含帶有ActionListener的JButton,這些JButton引用了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();
}
}
}
}
現在,當我執行代碼時,所有內容順利加載,我可以看到所有面板和其中的所有組件,但是當我單擊按鈕時,什么也沒有發生。 我猜想它與繼承有關,或者實際上我有幾個問題:
謝謝! 抱歉,如果這對您來說似乎很明顯,但是書或教程中的所有示例都有非常短的繼承示例和非常簡單的繼承示例,因此我無法以某種方式將這些簡單示例傳遞到代碼中。 謝謝!
您的主要問題是,僅在需要並且應該有一個時才創建兩個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()
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.