按钮和绘画方法

Buttons and paint method

我的按钮有问题。我知道它们正在工作,因为我已经通过 System.exit 退出问题来测试它们。这是我的输出:

http://imgur.com/Ks7mIFa

当我单击关闭按钮时,开关上的手柄应重新绘制到另一侧,关闭按钮应变为打开。当我点击打开按钮时,它应该做相反的事情。但是,按钮没有做任何事情。我做错了什么?

public class ProgrammingAssignment2 {

public static void main(String[] args) {

    boolean ison = false;

    // Objects
    Circuit circuitObject = new Circuit();
    Controller controllerObject = new Controller();
    Draw drawObject = new Draw();
    AllListeners listenerObject = new AllListeners();
    drawObject.window();

    circuitObject.buttons(drawObject, ison);
    controllerObject.openFile("Programming Assignment 2 Data.txt", drawObject);
}
}

Class 电路只创建按钮

import javax.swing.JButton;

public class Circuit {

public void buttons(Draw drawObject, boolean ison) {
    AllListeners listenerObject = new AllListeners();

    if (ison == true) {

        JButton openButton = new JButton("Close");
        openButton.addActionListener(listenerObject);
        openButton.setBounds(200, 100, 50, 20);
        drawObject.add(openButton);
    } else if (ison == false) {

        JButton closeButton = new JButton("Open");
        closeButton.addActionListener(listenerObject);
        closeButton.setBounds(50, 100, 50, 20);
        drawObject.add(closeButton);
    }
}
}

绘图 class 完成大部分工作。它创建所有图形并读入一个文本文件,其中包含每个 object(如开关和灯泡)的标题。

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.swing.JFrame;
import java.awt.Graphics;

public class Draw extends JFrame {

private String[] line = new String[5];
private int counter = 0;
private boolean ison;

public void window() {

    setSize(500, 500);
    setTitle("Programming Assignment 2");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setVisible(true);
}

public void readFile(String filename) {

    counter = 1;
    BufferedReader br = null;

    try {
        br = new BufferedReader(new FileReader(filename));


        for (int i = 0; i < 4; i++) {
            line[i] = br.readLine();
        }

    } catch (FileNotFoundException e) {
        String error = "File was not found";
        System.out.println(error.toString());
        System.out.println("or could not be opened.");
    } catch (IOException e) {
        System.out.println("Error reading from file.");
    } finally {
        try {
            br.close();
        } catch (IOException e) {
            System.out.println("Error closing file.");
        }
    }
}

public void paint(Graphics g) {
    Circuit circuitObject = new Circuit();
    super.paint(g);

    if (ison == true) {
        turnon(g);
        circuitObject.buttons(this, ison);
    } else {
        turnoff(g);
    }
}

public void setisOn() {
    ison = true;
}

public void setisOff() {
    ison = false;
}

public void turnoff(Graphics g) {
    // Title
    g.drawString(line[0], 150, 40);

    //Switch
    g.drawString(line[2], 130, 190);
    g.drawRect(100, 150, 100, 20);
    g.drawOval(115, 155, 10, 10);
    g.drawOval(175, 155, 10, 10);
    g.drawArc(140, 140, 20, 20, 180, -180);


    //off switch
    g.drawLine(160, 150, 182, 133);
    g.drawLine(157, 142, 173, 128);
    g.drawLine(173, 128, 182, 133);


    //Power Supply
    g.drawString(line[1], 50, 420);
    g.drawRect(50, 320, 50, 80);
    g.drawLine(50, 320, 70, 290);
    g.drawLine(100, 320, 120, 290);
    g.drawLine(70, 290, 120, 290);
    g.drawLine(120, 370, 120, 290);
    g.drawLine(120, 370, 100, 400);
    //plus
    g.drawLine(94, 310, 100, 310);
    g.drawLine(97, 307, 97, 313);
    // minus
    g.drawLine(100, 300, 107, 300);
    // pliers
    g.drawRect(70, 305, 5, 10);
    g.drawRect(90, 288, 5, 10);

    //lightbulb
    g.drawString(line[3], 400, 250);
    g.drawRect(400, 200, 20, 20);
    g.drawOval(395, 170, 30, 30);
    // pliers
    g.drawRect(400, 220, 5, 10);
    g.drawRect(415, 220, 5, 10);

    // plus wire to switch
    g.drawLine(72, 305, 120, 160);
    //bulb to switch
    g.drawLine(180, 160, 400, 230);
    //bulb to minus
    g.drawLine(90, 290, 420, 230);
}

public void turnon(Graphics g) {
    // Title
    g.drawString(line[0], 150, 40);

    //Switch
    g.drawString(line[2], 130, 190);
    g.drawRect(100, 150, 100, 20);
    g.drawOval(115, 155, 10, 10);
    g.drawOval(175, 155, 10, 10);
    g.drawArc(140, 140, 20, 20, 180, -180);

    //on switch
    g.drawLine(140, 150, 122, 133);
    g.drawLine(143, 142, 129, 128);
    g.drawLine(122, 133, 129, 128);

    //Power Supply
    g.drawString(line[1], 50, 420);
    g.drawRect(50, 320, 50, 80);
    g.drawLine(50, 320, 70, 290);
    g.drawLine(100, 320, 120, 290);
    g.drawLine(70, 290, 120, 290);
    g.drawLine(120, 370, 120, 290);
    g.drawLine(120, 370, 100, 400);
    //plus
    g.drawLine(94, 310, 100, 310);
    g.drawLine(97, 307, 97, 313);
    // minus
    g.drawLine(100, 300, 107, 300);
    // pliers
    g.drawRect(70, 305, 5, 10);
    g.drawRect(90, 288, 5, 10);

    //lightbulb
    g.drawString(line[3], 400, 250);
    g.drawRect(400, 200, 20, 20);
    g.drawOval(395, 170, 30, 30);
    // pliers
    g.drawRect(400, 220, 5, 10);
    g.drawRect(415, 220, 5, 10);

    // plus wire to switch
    g.drawLine(72, 305, 120, 160);
    //bulb to switch
    g.drawLine(180, 160, 400, 230);
    //bulb to minus
    g.drawLine(90, 290, 420, 230);
}
}

控制器做的不多。

public class Controller {

public void openFile(String filename, Draw drawObject) {
    drawObject.readFile(filename);
}
}

这是动作监听器class

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

public class AllListeners implements ActionListener {

public void actionPerformed(ActionEvent e) {
    Circuit circuitObject = new Circuit();
    Draw drawObject = new Draw();
    String buttonString = e.getActionCommand();

    if (buttonString.equals("Close")) {
        drawObject.setisOn();
        drawObject.repaint();

    } else if (buttonString.equals("Open")) {
        drawObject.setisOff();
        drawObject.repaint();

    } else {
        System.out.println("Unexpected error.");
    }
}
}

这段代码有很多主要问题,包括:

  • 在 JFrame 的绘制方法中直接绘制,这充满了问题,因为您可能会搞乱 JFrame 自己的复杂绘制。
  • 将程序逻辑置于绘画方法中,这是一种您无法完全控制何时或是否触发的方法,而且您不应放慢速度
  • 将组件创建代码放在绘画方法中。
  • 试图随意添加多个 JButton,而不是更改现有组件的状态。
  • 正在创建多个 Circuit 对象。
  • 尝试通过 setBounds(...) 使用绝对定位将组件放置在使用 BorderLayout 的容器中。

我建议你

  • 重新开始并废弃此代码。
  • 仅在 JPanel 的 paintComponent 方法中绘制,就像教程会告诉您的那样。
  • 一次性创建您的按钮并将它们添加到您的 GUI。
  • 从绘画(此处为 paintComponent)方法中取出所有程序逻辑,并在该方法之外更改所有对象状态,因为它们仅用于绘画和绘画。
  • 相反,逻辑应该属于控制器,并且应该通知按钮按下。
  • 所以考虑让按钮按下通知控件按下了什么,
  • 控件改变程序的状态(改变变量)
  • 然后调用 repaint 以便 paintComponent 方法可以使用这些变量来更改其绘图。
  • 此外,尽可能避免使用 setBounds 和 null 布局,而是使用布局 managers/borders/nested JPanels 来帮助您放置组件。