【问题标题】:Method called from first JFrame does nothing in second从第一个 JFrame 调用的方法在第二个中什么也不做
【发布时间】:2019-09-30 11:35:24
【问题描述】:

我在 MainGUI 类中将 JTextField "rfid" 设置为 setEnabled(false) 并创建了方法 setRfidEnabled 以便能够从另一个名为 CardLayout 的类中启用文本字段。 当我尝试通过按钮事件侦听器从 CardLayout 调用它时,它什么也不做,我的意思是文本字段,因为 System.out.print("LOL"); 工作正常。 MainGUI 包含 JFrame 并通过按钮调用 CardLayout 类中的另一个 JFrame。

当我初始化MainGUI类时,它有Thread[Thread-2,6,main],但是当我调用CardLayout时它变成Thread[AWT-EventQueue-0,6,main],和CardLayout本身一样。我试图让“rfid”不稳定,但没有成功。

---修改后的代码---

主界面:

public class MainGUI {
    JTextField rfid;
    JButton button;
    final JFrame frame;
    final JPanel pane;
    LayoutChanger layout = new LayoutChanger();
    public MainGUI() {
        rfid = new JTextField("", 10);
        button = new JButton("CardLayoutSwitch");
        frame = new JFrame("Main GUI Panel");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout(5,5));
        pane = new JPanel(new GridLayout(5, 5));
        frame.add(pane,BorderLayout.CENTER);
        pane.add(rfid);
        pane.add(button);
        rfid.setEnabled(false);
        button.setEnabled(true);
        frame.pack();
        frame.setVisible(true);
        frame.setLocationRelativeTo(null);
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed (ActionEvent e){
                layout.changeLayout(1);
            }
        });
    }
    public void setRfidEnabled() {
                System.out.println("LOL");
                rfid.setEnabled(true);
                button.setEnabled(false);
    }
}

LayoutChanger 类:

public class LayoutChanger {
    public static void main(String[] args) {
    MainGUI gui = new MainGUI();
    }

    public void changeLayout(int i){
        if (i == 1) {
            CardLayout card = new CardLayout();
        }
    }
}

卡片布局类:

public class CardLayout {
    JFrame frame;
    JButton manual;
    final JPanel pane;
    MainGUI gui = new MainGUI();
  public CardLayout() {
            manual = new JButton("UID MANUAL");
            frame = new JFrame("Card Scan Panel");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.setLayout(new BorderLayout(5, 5));
            pane = new JPanel(new BorderLayout(5, 5));
            manual.setPreferredSize(new Dimension(50, 25));
            frame.add(pane, BorderLayout.CENTER);
            pane.add(manual);
            frame.pack();
            frame.setVisible(true);
            frame.setLocationRelativeTo(null);
            manual.addActionListener(new ActionListener() {
             @Override
                public void actionPerformed (ActionEvent e){
                    gui.setRfidEnabled();
              }
          });
        }
}

【问题讨论】:

  • 请提供一个可运行的示例(又名minimal reproducible example),以便我们还可以重现您的“错误”行为并调试您的代码。请不要发布您当前的代码,而是尝试创建一个小的可运行示例来演示您的问题。如我所见,您使用线程来修改 Swing 小部件。这是个坏主意。所有修改都必须在 Swing-Thread 中执行。欲了解更多信息,请阅读concurrency in Swing
  • 你读过concurrency in Swing吗?当我在 Swing 代码中看到 Thread.sleep(2000) 时,我会收到红色警报。
  • 为什么在代码中使用线程?他们有必要吗?当需要在后台线程中做某事时,我使用SwingWorker。但在你的情况下,恕我直言,你不需要它。
  • 为什么要使用单独的线程来添加动作监听器?应在 EDT 上添加动作侦听器。此外,当它们因动作事件而被调用时,无论您用于添加动作侦听器的线程如何,都会在 EDT 上发生。
  • MainGUI gui = new MainGUI(); 创建一个新的主 gui,然后当您调用 gui.setRfidEnabled(); 时,它位于新的主 gui 上,而不是现有的。

标签: java multithreading swing jframe jtextfield


【解决方案1】:

正如@matt 在上面的 cmets 中所述

每次单击manual 按钮时,都会创建一个new MainGUI()

您需要在构造函数或ActionListener 中创建一个实例,并询问您是否已经拥有它的实例(即单例)并使用它。

如果您决定使用第一个,请将gui 声明为全局变量:

MainGUI gui = new MainGUI();

在您的ActionListener 上已将其更改为:

@Override
public void actionPerformed(ActionEvent e) {
    System.out.println(currentThread());
    gui.setRfidEnabled();
    //frame.dispose();
}

那么你就有了它的一个实例。

正如@Sergiy 所说,你并不真的需要所有这些线程

这里有一些关于如何使用ActionListeners的例子:

正如您在上述所有示例中所见,它们都不需要另一个线程来处理动作,使用线程的只是执行动画而不是对用户点击做出反应。

推荐教程:How to use Actions

【讨论】:

  • 如果我将MainGUI gui = new MainGUI() 声明为全局变量,我会得到Exception in thread "main" java.lang.StackOverflowError
  • 您需要创建一个新程序,将其发布为minimal reproducible example,删除所有这些线程并使其尽可能简单,然后我们可以提供更好的答案。使用演示您的问题的 MCVE 去编辑您的问题。如果你有问题,你可以在这里问我。但是以这个答案中链接中的所有示例为基础,这些都是 MCVE,因为您可以将它们复制粘贴到您的 IDE 中,并在不修改任何内容的情况下查看具有相同行为的相同 UI。
  • 你是对的,无用的线程毁了一切,我发布了 MCVE,现在的主要问题是 manual 按钮单击会带来新的整个 MainGUI 窗口,并且启用按钮的旧窗口仍然存在,我怎么能只是更新现有的MainGUI 窗口?
  • 阅读此答案的第一部分。那仍然不是minimal reproducible example,请正确缩进您的代码。现在你可以拨打第二个JFrame,那么这个问题就解决了。如果您仍然需要帮助发布另一个问题,但请确保准备好 MCVE,正如我所说,我可以指导您解决有关如何创建一个问题的具体问题,并且我已经解释了我们需要什么,1 个单一课程,新程序,而不是您的当前一个。
猜你喜欢
  • 1970-01-01
  • 2015-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 2014-06-05
  • 2021-03-01
相关资源
最近更新 更多