如何在第二个窗口中更新jFrame?

时间:2014-06-08 23:31:03

标签: java image swing jframe updates

我正在限时制作学校项目,导致代码混淆和混乱。我正在尝试打开两个jFrame,一个显示聊天界面,另一个显示图像。从第一个窗口调用actionPerformed()后,我想调用一种方法,多次更改第二个窗口上的图像,两者之间有一些延迟。但是,图像不会改变。

我认为我的问题出现了,因为在文本窗口中使用了一段示例代码,并尝试合并我自己的修改,而不是完全理解前者。在尝试查找这个问题时,我发现人们只是根据计时器和actionPerformed()更新了他们的jFrame,这实际上不是我想要的行为。

以下是有问题的代码:

 package main;

 import java.awt.event.*;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.image.BufferedImage;
 import java.io.File;
 import java.io.IOException;
 import java.util.concurrent.TimeUnit;
 import javax.imageio.ImageIO;
 import javax.swing.*;
 import javax.swing.text.BadLocationException;
 import javax.swing.text.Style;
 import javax.swing.text.StyleConstants;
 import javax.swing.text.StyleContext; 
 import javax.swing.text.StyledDocument;




public class Runner extends JPanel implements ActionListener {
     JFrame fFrame = new JFrame("Leonardo");
     protected JTextField textField;
     protected JTextPane textArea;
     private final static String newline = "\n";
     Dictionary dict = new Dictionary();
     StyleContext uContext = new StyleContext();
     StyleContext rContext = new StyleContext();
     Style uStyle;
     Style rStyle;
     JLabel lbl=new JLabel();


public Runner() {
    super(new GridBagLayout());

    styleInit();

    textField = new JTextField(20);
    textField.addActionListener(this);

    textArea = new JTextPane();
    textArea.setEditable(false);
    textArea.setBackground(Color.BLACK);
    JScrollPane scrollPane = new JScrollPane(textArea);

    //Add Components to this panel.
    GridBagConstraints c = new GridBagConstraints();
    c.gridwidth = GridBagConstraints.REMAINDER;

    c.fill = GridBagConstraints.HORIZONTAL;
    add(textField, c);

    c.fill = GridBagConstraints.BOTH;
    c.weightx = 1.0;
    c.weighty = 1.0;
    add(scrollPane, c);

}



public void actionPerformed(ActionEvent evt) {
    String text = textField.getText();
    StyledDocument doc = textArea.getStyledDocument();
    try {
        doc.insertString(doc.getLength(), "You: " + text + newline, uStyle);
    } catch (BadLocationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    textArea.setStyledDocument(doc);
    try { //this is the section which is not working properly
        changeLeonardo("Leonardo_Thinking.jpg");
        repaint();
        TimeUnit.SECONDS.sleep(1);
        for(int i = 0; i<3; i++){
            changeLeonardo("Leonardo_Talking1.jpg");
            TimeUnit.SECONDS.sleep(1);
            changeLeonardo("Leonardo_Talking2.jpg");
            TimeUnit.SECONDS.sleep(1);
        }
    } catch (InterruptedException e2) {
        // TODO Auto-generated catch block
        e2.printStackTrace();
    }
    try {
        doc.insertString(doc.getLength(), "Leonardo: " + Logic.respondIntelligent(text, dict)+ newline, rStyle);
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (BadLocationException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    textArea.setStyledDocument(doc);
    textField.selectAll();
    textArea.setCaretPosition(textArea.getDocument().getLength());
}

/**
 * Create the GUI and show it.  For thread safety,
 * this method should be invoked from the
 * event dispatch thread.
 */
private void styleInit(){
    uStyle = uContext.addStyle("User", null);
    uStyle.addAttribute(StyleConstants.Foreground, Color.WHITE);
    uStyle.addAttribute(StyleConstants.FontFamily, Font.SANS_SERIF);
    uStyle.addAttribute(StyleConstants.FontSize, new Integer(16));
    rStyle = rContext.addStyle("Robot", null);
    rStyle.addAttribute(StyleConstants.Foreground, Color.GREEN);
    rStyle.addAttribute(StyleConstants.FontFamily, Font.MONOSPACED);
    rStyle.addAttribute(StyleConstants.FontSize, new Integer(20));

}

private void changeLeonardo(String imgName){
    BufferedImage img = null;
    try {
        img = ImageIO.read(new File("C:\\resources\\" + imgName));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    System.out.println("C:\\resources\\" + imgName);
    ImageIcon icon=new ImageIcon(img);
    lbl.setIcon(icon);
    revalidate();
    repaint();
}

private void createAndShowGUI() {
    //Create and set up the window.
    JFrame frame = new JFrame("Leonardo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    fFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    fFrame.setLayout(new FlowLayout());
    changeLeonardo("Leonardo_Idle.jpg");
    frame.add(new Runner());
    frame.pack();
    frame.setVisible(true);
    fFrame.pack();
    fFrame.setVisible(true);
    fFrame.add(lbl);
}

public static void main(String[] args) {
    //Schedule a job for the event dispatch thread:
    //creating and showing this application's GUI.
    javax.swing.SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            Runner runner = new Runner ();
            runner.createAndShowGUI();
        }
    });
}

}

有些注意事项:

请原谅任何奇怪的名字,例如fFrame这样做可以使代码更好地反映学校项目。除此之外的所有类,如逻辑或字典都可以正常工作。代码不会抛出任何错误。我编辑了图像的文件名以保护隐私,但它们在代码中已满。

我确定此代码中还有其他问题,因为我通常不是图形专家,但如果您能够专注于更新问题,我将非常感谢。

谢谢。

1 个答案:

答案 0 :(得分:2)

所以,你想尝试两个基本概念,让你了解......

首先,为了在其他类上调用方法,需要对它进行引用。您并不总是希望自己创建该引用,有时,您只想提交预先创建的引用,这允许您修改引用对象的实际底层实现,而无需修改依赖于的代码它...

这通常是通过使用interface来实现的,因为它可以减少实施的风险,并且可以防止API的其余部分使用他们不应该参考的内容,但是这样做了#39}。另一个讨论点......

基本上,您需要将图像帧的引用传递给图形框架,以便图形框架可以在需要时调用图像框架。在下面的示例中,这是由BrowserPane完成的,需要SlideShowPane的实例通过它的构造函数传递给它...

SlideShowPane slideShowPane = new SlideShowPane();
//...
browser.add(new BrowserPane(slideShowPane));

BrowserPane可以使用此引用来调用SlideShowPane上的方法,特别是setPath方法......

slideShowPane.setPath(path);

这将导致SlideShowPane根据过去的目录/路径的内容开始新的幻灯片放映。

第二个概念是Swing是一个单线程环境,它也是一个事件驱动的环境。

第一部分意味着您无法阻止UI线程,否则它无法处理重绘请求等。第二部分重点介绍了一种可以解决此问题的方法。

在此示例中,我只使用javax.swing.Timer在图像之间设置了1秒的延迟。计时器在后台等待(在它自己的线程中),当被触发时,将在UI线程的上下文中调用已注册的ActionListener的{​​{1}}方法,使其成为可能可以安全地从内部更新UI。

这确保UI线程不会被阻止,并且可以继续处理新事件,同时为我们提供了一种执行延迟回调的便捷机制

请查看Concurrency in SwingHow to Use Swing Timers了解详情

actionPerformed