Java 如何在main中的runnable之外对JFrame GUI进行更改?

Java 如何在main中的runnable之外对JFrame GUI进行更改?,java,swing,user-interface,canvas,Java,Swing,User Interface,Canvas,我目前正在学习JavaGUI,我正在制作一个Java程序,您可以在GUI中编辑带有文本的形状。我创建了一个JFrame,其中包含一个自定义MyCanvas对象和一个文本字段。其思想是,MyCanvas对象有一个MouseListener,并将包含形状,单击这些形状将启用GUI中的文本字段,以便用户可以输入要在形状中显示的新消息。但是,我在GUI类的主方法中使用Runnable运行GUI,并且我无法从MyCanvas类启用文本框,因为它在Runnable之外。有人能帮我怎么做到这一点吗 以下是我的

我目前正在学习JavaGUI,我正在制作一个Java程序,您可以在GUI中编辑带有文本的形状。我创建了一个
JFrame
,其中包含一个自定义
MyCanvas
对象和一个文本字段。其思想是,
MyCanvas
对象有一个
MouseListener
,并将包含形状,单击这些形状将启用GUI中的文本字段,以便用户可以输入要在形状中显示的新消息。但是,我在GUI类的主方法中使用
Runnable
运行GUI,并且我无法从
MyCanvas
类启用文本框,因为它在
Runnable
之外。有人能帮我怎么做到这一点吗

以下是我的代码(伪代码)的基本结构:

//GUI类
公共类GUI扩展JFrame实现ActionListener{
私有静态MyCanvas c=new MyCanvas();//画布
私有静态文本字段编辑器=新建文本字段();//文本字段
公共静态void init(){
//初始化GUI元素并禁用文本框
}
公共静态void enableTextBox(){
//启用文本字段
}
公共静态无效disableTextBox(){
//禁用文本字段
}
已执行的公共无效操作(操作事件e){
//从文本框中获取消息
}
公共静态void main(字符串[]args){
//运行GUI框架
javax.swing.SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
init();
/*添加一个RectTextBox(一个包含文本的矩形对象,
*类(在别处定义)
*/
c、 addShape(新文本框(“Hello World”);
}
}
}
}
//画布类
类MyCanvas扩展JPanel实现MouseListener{
//画布上块的ArrayList
ArrayList块=新的ArrayList();
//执行器
公共MyCanvas(){
//初始化画布并将MouseListener添加到此画布
}
公共组件(图形g){
//在画布上绘制所有块
}
公共void addShape(矩形文本框b){
//将文本框b添加到块阵列列表
}
公共无效mouseClicked(MouseEvent e){
//检查是否单击了ArrayList中的任何块
/*启用GUI中的文本字段以输入消息,然后设置
*输入到块中的消息
*/
}
}

因此,您有了一个良好的开端。
MyCanvas
具有其他类可以调用的功能,例如,
addShape

// Canvas class
class MyCanvas extends JPanel implements MouseListener {
    // ArrayList of blocks on the canvas

    ArrayList<RectTextBox> blocks = new ArrayList<RectTextBox>();

    // Ctor
    public MyCanvas() {
        // Initialize canvas and add MouseListener to this canvas
    }

    public void paintComponent(Graphics g) {
        // Paints all blocks on canvas
    }

    public void addShape(RectTextBox b) {
        // Adds the text box b to the blocks ArrayList
    }

    public void mouseClicked(MouseEvent e) {
        // check if any blocks from the ArrayList is clicked

        /* enables the text field from GUI to enter messages, then set the
     * message entered to the block
         */
    }
}
然后,当
EditorPane
想要进行更改时,它可以使用
canvas
调用所需的方法

然后,我们构建您的UI,您将创建一个
MyCanvas
的实例,将该引用传递到
EditorPane
并将其添加到UI中,例如

public class EditorPane extends JPanel {
    private MyCanvas canvas;

    public EditorPane(MyCanvas canvas) {
        this.canvas = canvas;
        // Build UI as required
    }
}
EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        MyCanvas canvas = new MyCanvas();
        EditorPane editor = new EditorPane(canvas);

        JFrame frame = new JFrame();
        frame.add(canvas);
        frame.add(editor, BorderLayout.SOUTH);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
});

现在,就我个人而言,我会将大部分内容折叠到
界面
,以防止
EditorPane
MyCanvas
做更多的事情,但这是另一天的主题;)

要做的第一件事是,远离
静态
,它在这里对您的应用程序没有帮助。下一件事是在您的
MyCanvas
和控制类之间维护一个引用。然后,您可以在
MyCanvas
中提供控制器类可以调用的功能(例如设置要使用的形状类型)非常感谢!使用您的解决方案,有没有办法让画布也了解编辑器面板?我想让编辑器面板只在您单击其中一个形状时打开。可能不值得努力。我只想让它在您单击形状时,它所做的一件事“打开”画布
EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        MyCanvas canvas = new MyCanvas();
        EditorPane editor = new EditorPane(canvas);

        JFrame frame = new JFrame();
        frame.add(canvas);
        frame.add(editor, BorderLayout.SOUTH);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
});