如何在第二个窗口中更新jFrame? [英] How to update a jFrame in a second window?

查看:140
本文介绍了如何在第二个窗口中更新jFrame?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am working on a school project on limited time, leading to obfuscated code and much confusion. I am trying to have two jFrames open, one displaying a chat interface, the other displaying an image. Upon a call to actionPerformed() from the first window, I would like to call a method which changes the image that is on the second window, several times, with some delays in between. The image, however, does not change.

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

I think my issue has arose due to using a piece of example code for the text window, and trying to incorporate my own modifications, while not entirely understanding the former. In trying to look up this question, I only found people updating their jFrame based off of a timer and in actionPerformed(), which is not really the behavior I desire.

以下是有问题的代码:

 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 这样做是为了使代码反映出来学校项目更好。除此之外的所有类,如Logic或Dictionary都可以正常工作。代码不会抛出任何错误。我编辑了图像的文件名以保护隐私,但它们在代码中已满。

Please excuse any odd names, such as fFrame this is done to make the code reflect the school project better. All classes outside this, such as Logic or Dictionary work fine. The code throws no errors. I edited the filenames of the images for privacy, but they are full in the code.

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

I'm sure there are other issues abundant in this code, as I am typically not a graphics expert, but if you could please focus on the update issue, I would greatly appreciate it.

谢谢你。

推荐答案

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

So, two basic concepts you want to try and get your head around...

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

The first, in order to call a method on some other class, you need a reference to it. You don't always want to create that reference yourself, sometimes, you just want to be handed a pre-created reference, this allows you to modify the actual underlying implementation of the referenced object without needing to modify the code that relies on it...

这通常是通过使用接口来实现的,因为它减少了实施的风险并且阻止API的其余部分使用它们不应该引用的东西,但那是另一个讨论点......

This is typically best achieved through the use of a interface, as it reduces the exposure of the implementation and prevents the rest of the API doing things with the reference they shouldn't, but that's another discussion point...

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

Basically, you need to pass a reference of the image frame to the graph frame, so that the graph frame can call the image frame when it needs to. In the example below, this is done by the BrowserPane requiring an instance of the SlideShowPane to pass to it via it's constructor...

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

BrowserPane 可以使用此引用在 SlideShowPane 上调用方法,在这种情况下特别是 setPath 方法......

The BrowserPane can the use this reference to call methods on the SlideShowPane, in this case in particular, the setPath method...

slideShowPane.setPath(path);

这将导致 SlideShowPane 启动新的幻灯片放映基于目录/路径的内容过去。

This will cause the SlideShowPane to start a new slide show based on the contents of the directory/path past to it.

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

The second concept is the fact that Swing is a single threaded environment, it is also an event driven environment.

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

The first part means you can't block the UI thread, otherwise it can't process, amongst other things, repaint requests. The second part highlights a means by which you might be able to work around this.

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

In this example, I've simply used a javax.swing.Timer to set up a 1 second delay between images. The timer waits in the background (in it's own thread) and when triggered, will call the registered ActionListener's actionPerformed method within the context of the UI thread, making it safe to update the UI from within.

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

This ensures that the UI thread is not blocked and can continue to process new events, while providing us with a convenient mechanism for performing delayed callbacks

看看 Swing中的并发性如何使用Swing Timers 获取更多详细信息

Take a look at Concurrency in Swing and How to Use Swing Timers for more details

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class SlideShow {

    public static void main(String[] args) {
        new SlideShow();
    }

    public SlideShow() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
                GraphicsDevice gd = ge.getDefaultScreenDevice();

                Rectangle bounds = gd.getDefaultConfiguration().getBounds();
                System.out.println(bounds);

                SlideShowPane slideShowPane = new SlideShowPane();
                JFrame frame = new JFrame("Image");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(slideShowPane);
                frame.pack();
                int x = (bounds.x + (bounds.width / 2)) - frame.getWidth();
                int y = (bounds.y + (bounds.height - frame.getHeight()) / 2);
                frame.setLocation(x, y);
                frame.setVisible(true);

                JFrame browser = new JFrame("Browser");
                browser.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                browser.add(new BrowserPane(slideShowPane));
                browser.pack();
                x = (bounds.x + (bounds.width / 2)) + browser.getWidth();
                y = (bounds.y + (bounds.height - browser.getHeight()) / 2);
                browser.setLocation(x, y);
                browser.setVisible(true);
            }
        });
    }

    public class BrowserPane extends JPanel {

        private SlideShowPane slideShowPane;
        private JFileChooser chooser;

        private BrowserPane(SlideShowPane pane) {
            this.slideShowPane = pane;
            setLayout(new GridBagLayout());
            JButton browse = new JButton("...");
            add(browse);
            browse.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (chooser == null) {
                        chooser = new JFileChooser();
                        chooser.setMultiSelectionEnabled(false);
                        chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
                    }

                    switch (chooser.showOpenDialog(BrowserPane.this)) {
                        case JFileChooser.APPROVE_OPTION:
                            File path = chooser.getSelectedFile();
                            slideShowPane.setPath(path);
                            break;
                    }
                }
            });
        }

    }

    public class SlideShowPane extends JPanel {

        private File path;
        private Timer timer;
        private List<File> imageList;
        private int nextImage;
        private Image currentImage;

        public SlideShowPane() {
            imageList = new ArrayList<>(25);
            timer = new Timer(1000, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (imageList != null && !imageList.isEmpty()) {
                        nextImage++;
                        if (nextImage >= imageList.size()) {
                            nextImage = 0;
                        }
                        System.out.println("NextImage = " + nextImage);
                        do {
                            try {
                                File file = imageList.get(nextImage);
                                System.out.println("Load " + file);
                                currentImage = ImageIO.read(file);
                            } catch (IOException ex) {
                                currentImage = null;
                                nextImage++;
                                ex.printStackTrace();
                            }
                        } while (currentImage == null && nextImage < imageList.size());
                        repaint();
                    }
                }
            });
            timer.setInitialDelay(0);
        }

        public void setPath(File path) {
            System.out.println("SetPath");
            this.path = path;
            timer.stop();
            imageList.clear();
            currentImage = null;
            if (path.isDirectory()) {
                File files[] = path.listFiles(new FileFilter() {
                    @Override
                    public boolean accept(File pathname) {
                        String name = pathname.getName().toLowerCase();
                        return name.endsWith(".jpg")
                                        || name.endsWith(".jpeg")
                                        || name.endsWith(".png")
                                        || name.endsWith(".bmp")
                                        || name.endsWith(".gif");
                    }
                });
                if (files != null) {
                    System.out.println("Found " + files.length + " matches");
                    imageList.addAll(Arrays.asList(files));
                }
            }

            if (imageList.isEmpty()) {
                repaint();
            } else {
                System.out.println("Start timer...");
                nextImage = -1;
                timer.restart();
            }
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (currentImage != null) {
                Graphics2D g2d = (Graphics2D) g.create();
                int x = (getWidth() - currentImage.getWidth(this)) / 2;
                int y = (getHeight() - currentImage.getHeight(this)) / 2;
                g2d.drawImage(currentImage, x, y, this);
                g2d.dispose();
            }
        }

    }

}

这篇关于如何在第二个窗口中更新jFrame?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆