【问题标题】:Adding text to a label from another class - Simple Logic Issue将文本添加到另一个类的标签 - 简单的逻辑问题
【发布时间】:2012-11-09 09:19:24
【问题描述】:

我在一个名为FrameTest 的类中有一个标签和一个按钮,当我按下按钮时,会从Test 类中执行一个名为buttonpressed 的方法。在这个buttonpressed 方法中,我将为FrameTest 类中的标签设置一个文本。

我遇到的问题是,标签的文本没有设置。原因是我正在创建一个单独的对象来调用buttonpressed 方法;

public void actionPerformed(ActionEvent arg0) {
                    Test t = new Test();
                    t.buttonpress();
                }

我正在 Test 类的 main 方法中创建一个单独的对象来创建 UI。

public static void main(String[] args) {

         FrameTest f = new FrameTest();
         f.mainScreen();

    }

完整代码如下;

public class FrameTest extends JFrame {

private JPanel contentPane;
private JLabel lblLabel;
private FrameTest ft = this;

//private FrameTest frame;
/**
 * Launch the application.
 */
public  void mainScreen() {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                //FrameTest frame = new FrameTest();
                //setVisible(true);

                FrameTest frame = ft;
                frame.setVisible(true);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}


public void writeLabel(String k){
    this.lblLabel.setText(k);

}

public FrameTest() {
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setExtendedState(JFrame.MAXIMIZED_BOTH); 

    //setBounds(100, 100, 450, 300);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(new BorderLayout(0, 0));
    setContentPane(contentPane);

    lblLabel = new JLabel("LABEL");
    contentPane.add(lblLabel, BorderLayout.CENTER);

    JButton btnNewButton = new JButton("Press");
    btnNewButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Test t = new Test();
            t.buttonpress();
        }
    });
    contentPane.add(btnNewButton, BorderLayout.WEST);
    //pack();
    setLocationByPlatform(true);
}

}

测试类

public class Test {


public static void main(String[] args) {

     FrameTest f = new FrameTest();
     f.mainScreen();

}

public void buttonpress(){
     FrameTest f = new FrameTest();

     f.writeLabel("Button was pressed");

}

【问题讨论】:

标签: java swing jframe jlabel


【解决方案1】:

1) 不要不必要地扩展JFrame 类。

2) 不要使用setContentPane(),除非那是你想要的。而只是简单的JFrame#add(..)

3) 远离EventQueue 并使用SwingUtilities 阻止

4) 在设置JFrame可见之前不要忘记调用JFrame#pack();

5) Java 命名约定是 CamelCase 所以buttonPress() 是正确的不是buttonpress()

这是我做的一个例子(基本上你的代码是固定的):

Test.java:(这是主类,它将创建FrameTest 的实例并具有更改JLabel 文本的方法)

import javax.swing.SwingUtilities;

public class Test {

    private static FrameTest f;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                f = new FrameTest();
                f.mainScreen();
            }
        });
    }

    void buttonPress() {
        f.writeLabel("Hello");
    }
}

FrameTest.java:(该类将显示JFrame,并创建Test类的新实例以调用buttonPress()):

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class FrameTest {

    private JPanel panel;
    private JLabel lblLabel;
    private JFrame frame;

    private void initComponents() {
        frame = new JFrame("Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setExtendedState(JFrame.MAXIMIZED_BOTH);

        panel = new JPanel();
        panel.setBorder(new EmptyBorder(5, 5, 5, 5));
        panel.setLayout(new BorderLayout(0, 0));

        lblLabel = new JLabel("LABEL");
        panel.add(lblLabel, BorderLayout.CENTER);

        JButton btnNewButton = new JButton("Press");
        btnNewButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                Test t = new Test();
                t.buttonPress();
            }
        });

        panel.add(btnNewButton, BorderLayout.WEST);

        frame.add(panel);

        frame.setLocationByPlatform(true);
        frame.pack();
        frame.setVisible(true);
    }

    public void writeLabel(String k) {
        this.lblLabel.setText(k);
    }

    void mainScreen() {
        initComponents();
    }
}

【讨论】:

  • 课程TestJFrame 是错字吗?你是说Test 吗?
  • @sharonHwk 终于明白你想要什么了。 test 必须是主类,其中也包含更改 JLabel 的方法。查看更新
  • 谢谢。让我试试这个。但我有点喜欢以前的解决方案。
【解决方案2】:

- 第一种方法是使用Composition 原理,在Test.java class 中创建FrameTest.java实例,然后访问Label (使用此实例在 FrameTest.java 类中为 FrameTest 中的此标签使用 Getter Setters。

- 第二种方法是一种肮脏且快速的修复方法,在FrameTest.java 类中创建Label static 并直接从Test.java 类中设置值。瞧,它完成了.....

- 您的代码不工作的原因是您创建了一个非常新的FrameTest class 实例。所以现在你要么将FrameTest 对象引用变量 传递给buttonpress() 方法,要么将label static

例如:

public class FrameTest extends JFrame {

private JPanel contentPane;
public static JLabel lblLabel;

.....

.....

}

或者

public void buttonpress(FrameTest f) {
     f.writeLabel("Button was pressed");    
}

///////////////////////////////////////////////////////////// //////////////////

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

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

class FrameTest extends JFrame {

    private JPanel contentPane;
    private JLabel lblLabel;
    private FrameTest ft = this;

    public void mainScreen() {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {

                    FrameTest frame = ft;
                    frame.setVisible(true);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public void writeLabel(String k) {
        this.lblLabel.setText(k);

    }

    public FrameTest() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setExtendedState(JFrame.MAXIMIZED_BOTH);

        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        lblLabel = new JLabel("LABEL");
        contentPane.add(lblLabel, BorderLayout.CENTER);

        JButton btnNewButton = new JButton("Press");
        btnNewButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                Test t = new Test();

                t.buttonpress(FrameTest.this); // Passing the current object to
                                                // the Test class
                                                // You can use just "this" , but
                                                // as we are in an Anonymous
                                                // Inner Class here,
                                                // we have to use
                                                // "Class_name.this"

            }
        });
        contentPane.add(btnNewButton, BorderLayout.WEST);
        // pack();
        setLocationByPlatform(true);
    }

}

public class Test {

    public static void main(String[] args) {

        FrameTest f = new FrameTest();
        f.mainScreen();

    }

    public void buttonpress(FrameTest f) { // Receiving the reference to the
                                            // current frame, but remember
                                            // THOUGH IT SEEMS that we are passing the
                                            // reference but still in
                                            //  Here and in Java its always pass
                                            // by copy.( ie pass by value).

        f.writeLabel("Button was pressed");

    }
}

【讨论】:

  • 我尝试了第一种方法。但由于我有我的main() 方法(它是静态的),我将无法调用f.mainScreen(); 方法。
  • @sharonHwk 这是一个一般性的建议,请看我给出的示例代码
  • 我很想采用你的第一个解决方案,但你能告诉我如何从main() 类的main() 方法中调用f.mainScreen(); 方法
  • @sharonHwk 我已经根据您的要求根据第一个解决方案包含了整个工作代码......请查看编辑部分。
【解决方案3】:

将您的 FrameTest 对象传递给 buttonpress 方法并在那里使用它,而不是创建一个新对象:

public void buttonpress(FrameTest f) {
     f.writeLabel("Button was pressed");    
}

像这样改变方法的调用:

btnNewButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        Test t = new Test();
        t.buttonpress(FrameTest.this);
    }
});

你必须在这里使用FrameTest.this,因为你在一个实现ActionListener的匿名类中,所以普通的this会引用那个匿名类。

【讨论】:

  • 如何将参数FrameTest 添加到t.buttonpress();方法中?
  • 整个代码几乎是完美的,但从 Java 的角度来看,这是可行的。 Test t = new Test(); 不会创建 UI(这发生在 main() 方法中,这里从未调用过。
【解决方案4】:

只需更改您的 Test 类,如下所示

package com.test;

public class Test {

    private static FrameTest f;

    public static void main(String[] args) {

        f = new FrameTest();
        f.mainScreen();

    }

    public void buttonpress() {
        f.writeLabel("Button was pressed");
    }
}

实际问题是

  1. 您在 main 中创建了一个 FrameTest 变量 f 并向用户显示了 UI。
  2. 然后按下按钮,您再次创建了另一个FrameTest 实例f,它不会映射原始/第一个f

现在我将变量视为类变量,它按预期工作

【讨论】:

  • @DavidKroukamp Test 类不是 UI 创建类。 Test 是标签更新程序类。 UI 创建在 FrameTest 类完成。你可以试试我的代码并确保它有效。
猜你喜欢
  • 2011-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多