【问题标题】:Dynamically add a JPanel to a groupLayout将 JPanel 动态添加到 groupLayout
【发布时间】:2015-11-25 07:12:00
【问题描述】:

我尝试用 Java 为一个大学项目构建一个网络摄像头应用程序。到目前为止,我从来不需要 GUI,所以我没有这方面的经验,为此我使用了 netbeans 中的 gui builder。

现在的 GUI 看起来像这样:

它只是在 gui builder 中添加了一个 jPanel 和一个 jButton。

我要显示的图像是使用 openCV 拍摄的。这工作得很好,我得到一个缓冲图像。为了显示这个图像,我创建了一个 jPanel 的子类并更改了 paintComponent 方法。

package WebcamImageCapture;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import javax.swing.JPanel;

public class ImagePanel extends JPanel
{
    /**
     * Creates a new empty ImagePanel.
     */
    public ImagePanel()
    {
        this.image = null;
    }

    /**
     * Creates a new ImagePanel from BufferedImage img.
     * @param img The BufferedImage to display on the ImagePanel
     */
    public ImagePanel(BufferedImage img)
    {
        this.image = img;
    }

    @Override
    public void paintComponent(Graphics g)
    {
        super.paintComponent(g);
        g.drawImage(this.image, 0, 0, this.image.getWidth(), this.image.getHeight(), null);

        g.setColor(new Color(240, 160, 40));
        g.fillRect(10, 10, 25, 25);

        this.repaint();
    }

    /**
     * Sets the BufferedImage img to display on ImagePanel.
     * @param img The BufferedImage to display on the ImagePanel
     */
    public void setImage(BufferedImage img)
    {
        this.image = img;
    }

    private BufferedImage image;
}

GUI 类有成员openCameraButtonoutputPanel,这是您可以在屏幕截图中看到的元素。我尝试以下方法将我的imagePanel 添加到处理按钮的ActionPerformed 事件的方法内部的outputPanel

// create the custom jPanel
ImagePanel webcamFrame = new ImagePanel(img);
webcamFrame.setPreferredSize(new Dimension(640, 480));

this.outputPanel.getLayout().addLayoutComponent("webcamFrame", webcamFrame);
this.outputPanel.revalidate();
this.outputPanel.repaint();

this.revalidate();
this.repaint();

这不起作用 =(。我用谷歌搜索并测试了 2 天(还阅读了有关布局的 oracle 文档:documentation)没有找到解决方案。

所以主要问题是:

  1. 如何添加 ImagePanel?
  2. 我是否应该使用其他布局手动实现 GUI?

提前感谢您的帮助。

【问题讨论】:

    标签: java swing user-interface


    【解决方案1】:

    2.我应该用其他布局手动实现 GUI 吗?

    是的,IDE 生成的代码很难维护和更改。

    JFrame 默认使用 BorderLayout,因此您可以执行以下操作:

    ImagePanel = new ImagePanel();
    frame.add(imagePanel, BorderLayout.CENTER);
    
    JPanel south = new JPanel();
    JButton load = new JButton("Load Image");
    south.add(load);
    frame.add(south, BorderLayout.PAGE_END);
    

    所以想法是在设计时将面板添加到框架中。然后,每当您捕获图像时,您都会调用 setImage() 方法。您的 setImage() 方法中的代码是:

    this.image = img;
    repaint();
    

    您的paintComponent() 代码将更改为:

    if (image != null);
        g.drawImage(this.image, 0, 0, this.image.getWidth(), this.image.getHeight(), null);
    

    同时摆脱 repaint()。这将导致无限循环。

    【讨论】:

      【解决方案2】:

      我按照你的建议更改了我的代码...

      package WebcamImageCapture;
      
      import java.awt.Color;
      import java.awt.Graphics;
      import java.awt.image.BufferedImage;
      import javax.swing.JPanel;
      
      public class ImagePanel extends JPanel
      {
          /**
           * Creates a new empty ImagePanel.
           */
          public ImagePanel()
          {
              this.image = null;
          }
      
          /**
           * Creates a new ImagePanel from BufferedImage img.
           * @param img The BufferedImage to display on the ImagePanel
           */
          public ImagePanel(BufferedImage img)
          {
              this.image = img;
          }
      
          @Override
          public void paintComponent(Graphics g)
          {
              if(this.image != null)
              {
                  super.paintComponent(g);
                  g.drawImage(this.image, 0, 0, this.image.getWidth(), this.image.getHeight(), null);
      
                  g.setColor(new Color(240, 160, 40));
                  g.fillRect(10, 10, 25, 25);
      
                  System.out.println("image drawn ...");
              }
              else
              {
                  System.out.println("image not drawn ...");
              }
          }
      
          /**
           * Sets the BufferedImage img to display on ImagePanel.
           * @param img The BufferedImage to display on the ImagePanel
           */
          public void setImage(BufferedImage img)
          {
              this.image = img;
              this.repaint();
          }
      
          private BufferedImage image;
      }
      

      ...并手动创建了 GUI。

      private void init()
      {
          this.imageOutput = new ImagePanel();
          this.add(imageOutput, BorderLayout.CENTER);
      
          this.openCameraButton = new JButton("open camera");
          this.openCameraButton.addActionListener(new java.awt.event.ActionListener() {
              @Override
              public void actionPerformed(java.awt.event.ActionEvent evt) {
                  openCameraButtonActionPerformed(evt);
              }
          });
      
          JPanel navigation = new JPanel();
          navigation.add(this.openCameraButton, BorderLayout.PAGE_END);
      
          this.add(navigation);
          this.setTitle("Webcam");
          this.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
      
          this.pack();
      }
      

      openCameraButtonActionPerformed 方法中,我拍摄了图像并使用ImagePanelsetImage 方法对其进行设置。

      this.imageOutput.setImage(img);

      但不幸的是,什么也没发生。如果我执行以下操作,我会得到一个包含图像的新窗口。

      JFrame myFrame = new JFrame("myFrame");
      ImagePanel out = new ImagePanel(img);
      myFrame.add(out);
      myFrame.pack();
      myFrame.setVisible(true);
      

      我做错了什么?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-11
        • 2023-03-05
        • 1970-01-01
        相关资源
        最近更新 更多