【问题标题】:Adding two components from the same class in a JFrame在 JFrame 中添加来自同一类的两个组件
【发布时间】:2013-09-09 03:31:01
【问题描述】:

所以对于一些家庭作业,我必须创建一个表示余额的条形图。 只是为了熟悉图形/组件,我只想通过在屏幕上放置两个框来开始。似乎第一个框是“绘制”然后第二个框只是覆盖它? 这是两个类。

主类 - BalanceChart.java

package balancechart;

import javax.swing.*;

public class BalanceChart {

Double[] Props = new Double[6];

public static void main(String[] args) {
   JFrame f = new JFrame("Balance Chart");
   f.setSize(500, 500);
   f.setDefaultCloseOperation(
   JFrame.EXIT_ON_CLOSE);
   ChartComponent ccOne = new ChartComponent(50, 50, 100, 200);
   ChartComponent ccTwo = new ChartComponent(10, 10, 10, 10);
   f.add(ccOne);
   f.add(ccTwo);
   f.setVisible(true);
}

private void getProps(){
    //ignore
}

}

组件类 - ChartComponent.java

package balancechart;

import javax.swing.*;
import java.awt.*;

public class ChartComponent 
extends JComponent {

private int x, y, w, h;

public ChartComponent(int x, int y, int w, int h){
  this.x = x;
  this.y = y;
  this.w = w;
  this.h = h;
}

public void paintComponent(Graphics g){
  Graphics2D g2 = (Graphics2D) g.create();
  g2.setColor(Color.RED);
  g2.fillRect(w, h, x, y);
}

}

我猜这与我对 JFrame 的 2 个添加过程有关,我只是不知道该怎么做。

提前致谢

【问题讨论】:

    标签: java swing jframe components abstract


    【解决方案1】:

    您需要跑到最近的布局管理器教程,而不是步行。在那里您会发现 JFrame 的 contentPane 默认使用 BorderLayout,当您将组件添加到使用 BorderLayout 的容器而不使用其他常量时,它会默认添加到 BorderLayout.CENTER 位置,覆盖之前添加的任何内容。

    一种解决方案是创建另一个使用所选布局的 JPanel,甚至可能只保留 JPanel 的默认 FlowLayout,将组件添加到其中,然后将该 JPanel 添加到 JFrame。

    即,

    ChartComponent ccOne = new ChartComponent(50, 50, 100, 200);
    ChartComponent ccTwo = new ChartComponent(10, 10, 10, 10);
    JPanel container = new JPanel(); // JPanel uses FlowLayout by default
    container.add(ccOne);
    container.add(ccTwo);
    f.add(container, BorderLayout.CENTER); // just to be clear
    f.pack();
    f.setVisible(true);
    

    请查看此教程链接:Laying Out Components Within a Container


    编辑
    正如 MadProgrammer 指出的那样,这里还有另一个问题:

    public void paintComponent(Graphics g){
      Graphics2D g2 = (Graphics2D) g.create();
      g2.setColor(Color.RED);
      g2.fillRect(w, h, x, y);
    }
    

    因为你不调用 super 方法,所以旧图像不会在需要时被清除,如果你尝试通过改变 w、h、x 或 y 来做一些动画,这将非常重要在摆动计时器中。要解决这个问题,请务必调用 super 的方法。此外,paintComponent 应该是protected 而不是public,并且您应该使用@Override 注释来确保您正确地覆盖了该方法。如果您绝对需要创建一个新的 Graphics 上下文,那么您应该在完成后将其处理掉,以免资源耗尽。不要不要处理 JVM 提供给您的 Graphics 上下文(例如传递给您的 paintComponent(...) 方法参数的上下文,因为这可能会产生不必要的副作用:

    @Override
    protected void paintComponent(Graphics g){
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g.create();
      g2.setColor(Color.RED);
      g2.fillRect(w, h, x, y);
      g2.dispose(); // only do this if you create your own Graphics context
    }
    

    编辑 2
    此外,您应该养成尝试不设置任何大小的习惯,而是让 GUI 的组件和布局管理器在被要求时设置自己的大小,因为这将导致更令人愉悦和灵活的 GUI 程序。


    编辑 3
    您在评论中声明:

    我修复了代码,但我似乎没有在任何地方出现 2 个红色方块,并且窗口以非常小的尺寸启动。我还有很多事情要做,我不明白为什么添加的代码会这样做。

    您的问题是您的JComponent,ChartComponent 的默认preferredSize 将是0,0 或1,1;我忘了哪个,但没关系,因为在任何一种情况下,组件都不够大而无法看到。为了解决这个问题,给你的类一个 getPreferredSize() 方法覆盖,帮助设置它的大小。例如:

    import java.awt.Color;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Graphics2D;    
    import javax.swing.*;
    
    public class BalanceChart {
    
       Double[] Props = new Double[6];
    
       public static void main(String[] args) {
          JFrame f = new JFrame("Balance Chart");
          //  f.setSize(500, 500);
          f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          ChartComponent ccOne = new ChartComponent(50, 50, 100, 200);
          ChartComponent ccTwo = new ChartComponent(10, 10, 10, 10);
          JPanel container = new JPanel();
          container.add(ccOne);
          container.add(ccTwo);
          f.add(container);
          f.pack();
          f.setLocationByPlatform(true);
          f.setVisible(true);
       }
    
       private void getProps() {
          // ignore
       }
    
    }
    
    class ChartComponent extends JComponent {
    
       private static final int PREF_W = 400;
       private static final int PREF_H = PREF_W;
       private int x, y, w, h;
    
       public ChartComponent(int x, int y, int w, int h) {
          this.x = x;
          this.y = y;
          this.w = w;
          this.h = h;
       }
    
       @Override
       public Dimension getPreferredSize() {
          return new Dimension(PREF_W, PREF_H);
       }
    
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2 = (Graphics2D) g.create();
          g2.setColor(Color.RED);
          g2.fillRect(w, h, x, y);
          g2.dispose();
       }
    
    }
    

    【讨论】:

    • (super.paintComponent ;))
    • 感谢您的快速回复和教程链接。我修复了代码,但我似乎没有在任何地方出现 2 个红色方块,并且窗口以非常小的尺寸启动。我还有很多东西要做,我不明白为什么添加的代码会这样做。
    猜你喜欢
    • 2021-12-14
    • 2022-06-30
    • 2013-07-24
    • 1970-01-01
    • 2016-07-12
    • 2015-02-27
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多