2

编辑:我发现了我的问题,但仍然不知道为什么会发生这种情况,我还没有完成 Mehran Sahami 教授(斯坦福大学)的在线讲座,如果我继续播放讲座视频,也许我会找到答案.

问题是我在我的按钮方法之前删除了我的其他组件方法以有效地发布空间,所以我应该把我的JToggleButton 方法放在我的主要JFrame方法之后让它工作,但是如果我的 其他组件也继承其他类怎么办?我应该首先使用哪种方法来使所有组件正常工作?我会通过更多地练习java来发现。

感谢@Dan 和@SebVb 的回答和建议,如果这只是初学者的错误,请见谅:)

我现在正在学习 java 一个月,并且已经有了简单的学习项目,但是现在我遇到了JToggleButton,ItemEventactionPerformedIf 语句中的问题。

我已经搜索了一个星期来寻找在另一个类中使用actionPerformedif 语句的示例,ItemEvent但我找不到相同的问题来产生工作结果。

我正在尝试制作一个仅在选择切换按钮时才会扫描的窗口扫描仪,然后JPanel使用缓冲图像进行绘制(每 100 毫秒重绘一次)并在取消选择切换按钮时将其处理,但我认为我的做法是错误的。我有一个主类和两个子类,如下所示:

主类:

public class WindowScanner {
    public static void main(String[] args) {
        new Window().setVisible(true);
    }
}

窗口类:

class Window extends JFrame {
    static JToggleButton captureButton = new JToggleButton("CAPTURE");

    @SuppressWarnings("Convert2Lambda")
    public Window() {
        // JFrame looks codes

        /** EDIT: these components method should be written after button method
        * JPanel looks codes
        * JLabel looks codes
        * END EDIT
        */

        add(captureButton);
        // capture button default looks code
        ItemListener captureListener = new ItemListener(){
            @Override
            public void itemStateChanged(ItemEvent captureButtonEvent) {
                int captureState = captureButtonEvent.getStateChange();
                if(captureState == ItemEvent.SELECTED){
                    // capture button SELECTED looks code
                    System.out.println("capture button is selected");
                } else if(captureState == ItemEvent.DESELECTED){
                    // capture button DESELECTED looks code
                    System.out.println("capture button is deselected");
                }
            }
        }; captureButton.addItemListener(captureListener);
    }
}

扫描仪类:

public class Scanner extends Window {

    private static BufferedImage boardCaptured;
    static int delay = 100;

    protected BufferedImage boardScanned(){
        return boardCaptured;
    }

    @SuppressWarnings("Convert2Lambda")
    public static void Scan() {
        if (captureButton.isSelected()) {
            ActionListener taskPerformer = new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent captureEvent) {
                    try {
                        // capturing method
                    } catch (AWTException error) {
                        // AWTException error method
                    }
                    // is this the right place to put JPanel code?
                    JPanel panel = new JPanel();
                    boardCaptured = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);
                    Graphics2D graphic = boardCaptured.createGraphics();
                    panel.setSize(500,500);
                    panel.paint(graphic);
                    panel.revalidate();
                    panel.repaint();
                }
            }; new Timer(delay, taskPerformer).start();
        } else {
            // this suppose to end capturing if capture button isSelected() == false
        }
    }
}

所以这是我的问题:

  1. 我真的必须将 Main 类与 Window 类分开吗?什么原因?
  2. 如何让我在 Scan 方法中的 if 语句 JToggleButton从 Window 类中识别我的状态?这是不可能的,我有一个错误的方法来做到这一点?
  3. 在 Scanner 类中,我无法为我的actionPerformed (Netbeans 总是将其检查为错误)进行获取/设置,但为什么我可以为我的 BufferdImage
  4. 如果我无法解决第 3 个问题,我该如何使用 If 语句停止捕获Timer.stop()?还是我又走错路了?
  5. 是否会生成我JPanel的扫描仪课程并为我的缓冲图像制作查看器?

PS我很抱歉它的问题很拥挤,我尽量不发多个帖子,所以我发了一个有多个问题的帖子。如果之前有答案,请注意我,老实说我找不到它或者用错误的标签搜索它。

4

2 回答 2

1

我认为有一种更简单的方法可以做你想做的事。按顺序回答您的问题

  1. 将主类与您的 Window 类分开,您可以在任何地方重用您的 Windows 类。只在主类上初始化 GUI 对象是一个很好的做法

  2. 你为什么不让你的 JToggleButton 私有和一个可以访问他状态的方法?此外,使用静态字段,您的所有 Windows 实例都将共享相同的 JToggleButton。

  3. 这是一个包含您的 actionPerformed 方法的匿名类。如果你想看到它,你必须创建一个内部类。

  4. 我认为你的方法是错误的。使用一个线程,它会以特定的延迟启动你的重绘会更好。如果您创建一个扩展 Runnable 的类,您可以检查按钮的状态,然后执行相应的操作

  5. 您的 JPanel 在 ActionListener 中,我从未见过,而且我认为它不能正常工作。

在较短的版本中

  1. 将 JPanel、BufferedImage 和 JToggleButton 放入 Window 类中
  2. 选择 JToggleButton 时创建一个特定线程来进行重绘
于 2016-01-19T09:38:37.863 回答
1

这是我认为您想要做的简单版本。可以对其进行编辑以包含您的变量,例如boardCaptured. 这段代码主要描述了如何从不同的类中获取组件。

Main.java(包含一个java文件中的所有类)

import javax.swing.JLabel;
import javax.swing.JToggleButton;
import javax.swing.JFrame;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.Random;
import javax.swing.Timer;

class WindowScanner extends JFrame {
    private JLabel label;
    private JToggleButton captureButton = new JToggleButton("CAPTURE");

    WindowScanner() {
        super("Fist Window");
        setSize(150, 100);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        setLayout(new FlowLayout());
        add(captureButton);
        setVisible(true);

        new Scanner(this);
    }

    public JToggleButton getCaptureButton() {
        return captureButton;
    }
}

class Scanner extends JFrame {
    private WindowScanner wS;
    private int delay = 1000;
    private Timer t = new Timer(delay, new taskPerformer());

    Scanner(WindowScanner wS) {
        super("Second Window");
        this.wS = wS;
        setBounds(200,0,500,500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        wS.getCaptureButton().addActionListener(new taskPerformer());
    }

    private Color randomColor() {
        Random rand = new Random();
        float r = rand.nextFloat() / 2f ;
        float g = rand.nextFloat() / 2f;
        float b = rand.nextFloat() / 2f;
        Color randomColor = new Color(r, g, b);
        return randomColor;
    }

    private class taskPerformer implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent captureEvent) {
            if(captureEvent.getSource() == wS.getCaptureButton()) {
                if (wS.getCaptureButton().isSelected()) {
                    t.start();
                } else {
                    t.stop();
                }
            }

            if(captureEvent.getSource() == t) {
                getContentPane().setBackground(randomColor());
                revalidate();
                repaint();
            }
        }
    }
}

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

这段特定的代码JFrame使用来自 的计时器每秒将背景颜色更改为随机颜色javax.swing.timer。此代码描述了如何从不同的类中获取组件或变量(如果您更改它)。

主要是这些代码片段允许它。

1

public JToggleButton getCaptureButton() {
    return captureButton;
}

这允许其他类获取组件。

2

private WindowScanner wS;

Scanner(WindowScanner wS) {
    ...
    this.wS = wS;
    ...
}

这使得当前实例WindowScannerWindowScanner声明的实例在Scanner同一个实例中。

注意:查看使用public getters and setters.

至于你列出的 5 个问题。

1)我真的必须将 Main 类与 Window 类分开吗?什么原因?

在大多数情况下,是的。正如SebVb所说,这是一种很好的做法。但是,如果您希望他们在同一个班级,您可以这样做。

import javax.swing.JToggleButton;
import javax.swing.JFrame;
import java.awt.FlowLayout;

public class Test extends JFrame {
    private JToggleButton captureButton = new JToggleButton("CAPTURE");

    Test() {
        super("Fist Window");
        setSize(150, 100);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        setLayout(new FlowLayout());
        add(captureButton);
        setVisible(true);
    }

    public JToggleButton getCaptureButton() {
        return captureButton;
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                Test frame = new Test();
            }
        });
    }
}

2) 如何让我在 Scan 方法中的 if 语句从 Window 类中识别我的 JToggleButton 的状态?这是不可能的,我有一个错误的方法来做到这一点?

您使用了错误的方法来执行此操作。请参阅我在上面放置的代码和代码片段,了解如何正确执行此操作。(使用public getters。)

3) 在 Scanner 类中,我无法为我的 actionPerformed 进行获取/设置(Netbeans 总是将其检查为错误),但为什么我可以为 BufferdImage 进行设置?

我不能完全说我确定你在问什么,但请查看我上面的代码,看看是否有帮助。如果它没有留下评论试图完全解释你的意思。

4) 如果我无法得到第 3 个问题,我该如何使用 Timer.stop() 来制作 If 语句以停止捕获?还是我又走错路了?

在我的代码中,我向您展示了这如何与JToggleButton. 请参阅下面的代码片段

private class taskPerformer implements ActionListener {
    @Override
    public void actionPerformed(ActionEvent captureEvent) {
        if(captureEvent.getSource() == wS.getCaptureButton()) {
            if (wS.getCaptureButton().isSelected()) {
                t.start();
            } else {
                t.stop();
            }
        }

        if(captureEvent.getSource() == t) {
            getContentPane().setBackground(randomColor());
            revalidate();
            repaint();
        }
    }
}

此代码表示当JToggleButton触发时,ActionEvent如果它被选中则启动计时器t.start(),或者如果它未被选中,则停止计时器t.stop()

5) 是否会生成我在 Scanner 类中的 JPanel 并为我的缓冲图像制作一个查看器?

同样,我不完全确定您在问什么,但这是我最好的猜测。你有两个选择。

1

直接放在boardCaptured框架上。

paint(graphic);
repaint();
revaildate();

2

创建一个JPanel像你一样的,但在外面ActionListener

JPanel panel = new JPanel()
boardCaptured = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);
Graphics2D graphic = boardCaptured.createGraphics();
panel.setSize(500,500);
panel.paint(graphic);
add(panel);

private class taskPerformer implements ActionListener {
    if(captureEvent.getSource() == t) {
        panel.paint(graphic);
        panel.revalidate();
        panel.repaint();
    }
}
于 2016-01-19T10:04:58.957 回答