当前位置: 首页 > 面试题库 >

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

皇甫逸清
2023-03-14
问题内容

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

我认为我的问题是由于在文本窗口中使用了一些示例代码,并试图合并我自己的修改而没有完全理解前者。在尝试查找此问题时,我仅发现人们根据计时器和in来更新其jFrame
actionPerformed(),这并不是我想要的行为。

这是有问题的代码:

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

我确定这段代码中还有很多其他问题,因为我通常不是图形专家,但是如果您能专注于更新问题,我将不胜感激。

谢谢。


问题答案:

因此,您想尝试两个基本概念…

首先,为了在其他类上调用方法,您需要对其进行引用。您不一定总是要自己创建该引用,有时,您只是想获得一个预先创建的引用,这使您可以修改引用对象的实际基础实现,而无需修改依赖于该对象的代码。
..

通常,最好通过使用来达到最佳效果interface,因为它减少了实现的公开性,并阻止了其余API使用他们不应该使用的引用来做事,但这是另一个讨论要点…

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

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

BrowserPane可以使用该引用调用的方法SlideShowPane,在这种情况下,尤其是setPath方法…

slideShowPane.setPath(path);

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

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

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

在此示例中,我仅使用a
javax.swing.Timer来设置图像之间的1秒延迟。计时器在后台(在其自己的线程中)等待,并在触发时将在UI线程的上下文内调用已注册ActionListeneractionPerformed方法,从而可以安全地从内部更新UI。

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

查看Swing中的并发性和如何使用Swing计时器以了解更多详细信息

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();
            }
        }

    }

}


 类似资料:
  • 问题内容: 我正在尝试从第二个窗口切换到第三个窗口。但是无法处理第三个窗口。有人可以帮助我解决此问题。我已经使用比较窗口标题的逻辑,但是它不起作用。代码======================= 错误堆栈跟踪: 问题答案: 这是切换到 并单击 按钮的完整代码块: 我的IDE控制台上的输出是:

  • 所以我一直在为openGL课程玩土壤,我的项目遇到了一个奇怪的问题。我将显示两个窗口,每个窗口包含三个视口,在其中绘制一个带纹理的立方体或椭圆体,以展示我对深度和面剔除的理解。现在,所有形状都正确绘制,并且当单独测试时,它看起来完全符合预期,但是一旦我同时启用两个窗口,纹理就会在第一个窗口中禁用。我之前已经发布了类似的问题,所以只是为了澄清,如果我禁用窗口二,或者如果我在窗口二中使用窗口一绘制功能

  • 我有一个用例,其中我收到包含不同信息集的事件流,并希望对它们执行聚合。对于这些聚合中的每一个,都需要多个翻滚窗口,例如:每日,每周,每月,每年等。 聚合最初是所看到的计数的基本加法,但后来可能是对这些事件的一些分析/联接处理。因此,如果一个事件A每天来一次,另一个事件B每周来一次,结果将是这样的: 用例只是围绕翻滚的窗口而不是滑动窗口,我正在研究如何实现这个用例。主要问题是我不想等到窗口结束,而是

  • 第一课: 新建一个窗口 简介 欢迎来到第一课! 在学习OpenGL之前,我们将先学习如何生成,运行,和玩转(最重要的一点)课程中的代码。 预备知识 不需要特别的预备知识。如果你有C、Java、Lisp、Javascript等编程语言的经验,那么理解课程代码会更快;但这不是必需的;如果没有,那么也仅仅是同时学两样东西(编程语言+OpenGL)会稍微复杂点而已。 课程全部用“傻瓜式C++”编写:我费了

  • 问题内容: 我正在研究一些计算机视觉算法,我想展示一个numpy数组在每个步骤中如何变化。 现在有效的是,如果我在代码末尾有一个简单的代码,则该窗口将显示并显示最终图像。 但是,我想做的是在每次迭代中更改图像时更新并显示imshow窗口。 因此,例如,我想这样做: 问题在于,只有完成整个计算后,Matplotlib窗口才会被激活。 我已经尝试了原生matplotlib和pyplot,但是结果是一样

  • 我的当前程序将向用户输出图像,并根据用户输入,根据需要重新调整图像。 长话短说,我试图在图像文件中找到圆形对象。我将使用Hough圆变换。然而,因为我在图像中的许多圆不是“完美圆”,所以我正在做一个“猜测”圆半径的算法。但是,我希望允许用户根据需要重新调整半径。 有没有办法要求用户输入,然后根据用户输入,重新调整imshow()中的窗口?现在,imshow()拒绝显示实际的窗口,直到我使用cv2.