【问题标题】:Updating a GUI panel, Java更新 GUI 面板,Java
【发布时间】:2013-12-23 08:58:08
【问题描述】:

我是一名 Java GUI 初学者,在让我的面板按照我想要的方式更新时遇到了一些麻烦。基本上,当用户单击我的 GUI 中的一个按钮时,屏幕上当前的形状应更改为与按钮按下对应的任何形状。我的代码如下。更新的形状在显示之前被原始形状覆盖的问题。

我很确定问题与我的 ButtonListeners 有关。我在打印语句中添加了查看何时调用不同的绘制方法,这是单击按钮后的结果:

矩形 矩形 矩形 ddd 椭圆形 矩形

显然更新正在发生,但随后被原始形状覆盖!有人能告诉我为什么会发生这种最终覆盖吗?!

我已经包含了我用作参考的 FigurePanel 类。

import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class miniCADFrame extends JPanel {

    private ButtonPanel buttons = new ButtonPanel();
    private CanvasPanel canvas = new CanvasPanel();

    public miniCADFrame() {
         //Constructor, creates the mother panel
         this.setLayout(new BorderLayout());
         this.add (canvas,BorderLayout.CENTER);
    }
    //******** BUTTONLISTENER************************
    private class ButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent event) {    //Paint the figure associated with the button click
                canvas.add(new FigurePanel(FigurePanel.OVAL), BorderLayout.CENTER);
                canvas.revalidate();
                canvas.repaint();
                System.out.println("ddd");

            }
    }

    private class ButtonPanel extends JPanel {

        private JButton[] Jbuttons = new JButton[11];
        //Constructor
        ButtonPanel() {

            setLayout(new GridLayout(4, 4)); 

            // Create buttons to attach to the buttons panel
            Jbuttons[0] = new JButton("Change Colour");
            Jbuttons[1] = new JButton("Up");
            Jbuttons[2] = new JButton("Text");
            Jbuttons[3] = new JButton("Left");
            Jbuttons[4] = new JButton("Enlarge");
            Jbuttons[5] = new JButton("Right");
            Jbuttons[6] = new JButton("Rectangle");
            Jbuttons[7] = new JButton("Down");
            Jbuttons[8] = new JButton("Circle");
            Jbuttons[9] = new JButton("Save");
            Jbuttons[10] = new JButton("Load");

            //Add the buttons to the buttons panel
            for (int i=0; i<11; i++) {
                Jbuttons[i].addActionListener(new ButtonListener());
                add(Jbuttons[i]);
            }
    }
    }

class CanvasPanel extends JPanel {

        //Constructor
        CanvasPanel() {
            // Create "canvas" to hold a label for the buttons panel along with the button panel itself
             this.setLayout(new BorderLayout());
             this.add(new JLabel("CONTROL PANEL"),BorderLayout.NORTH);
             this.add(buttons, BorderLayout.WEST); //add the button panel to the canvas panel

             //test
             this.add(new FigurePanel(FigurePanel.RECTANGLE), BorderLayout.CENTER);
        }
}
}

FigurePanel 类:

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

public class FigurePanel extends JPanel {

    // Define constants
     public static final int LINE = 1;
     public static final int RECTANGLE = 2;
     public static final int OVAL = 4;

     private int type;

     /** Construct a default FigurePanel */
     public FigurePanel() {
     }

     /** Construct a FigurePanel with the specified type */
     public FigurePanel(int type) {
     this.type = type;
     }

     /** Draw a figure on the panel */
     protected void paintComponent(Graphics g) {
         //Create blank canvas
         super.paintComponent(g);

         // Get the appropriate size for the figure
         int width = getWidth();//width of the component
         int height = getHeight();//height of the component

        switch (type) {
         case LINE: // Display a single line
             g.drawLine(10, 10, width - 10, height - 10);
             break;
         case RECTANGLE: // Display a rectangle
             g.drawRect((int)(0.1 * width), (int)(0.1 * height),
             (int)(0.8 * width), (int)(0.8 * height));
             break;
         case OVAL: // Display an oval
          g.drawOval((int)(0.1 * width), (int)(0.1 * height),
          (int)(0.8 * width), (int)(0.8 * height));
         }
 }
      /** Set a new figure type */
      public void setType(int type) {
      this.type = type;
      }

      /** Return figure type */
      public int getType() {
      return type;
      }

      /** Specify preferred size */
      public Dimension getPreferredSize() {
          return new Dimension(80, 80);
      }
}

最后,这是我的框架类:

import java.awt.*;

import javax.swing.*;

public class miniCAD extends JFrame {
    //Constructor for our extended frame class

    public miniCAD() { 

    //Initialize our custom frame
    miniCADFrame frame = new miniCADFrame();    

    add(frame, BorderLayout.CENTER);

    }

     /** Main method */
     public static void main(String[] args) {
     miniCAD frame = new miniCAD();
     frame.setTitle("minCAD");
     frame.setSize(1000, 1000);
     frame.setLocationRelativeTo(null); // Center the frame
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     frame.setVisible(true);
     }
 }

感谢您的帮助!

【问题讨论】:

    标签: java swing user-interface jpanel


    【解决方案1】:

    我可以提出两个可能的原因。

    1. canvas.repaint(); 之前调用canvas.revalidate(); 以更新布局。
    2. 检查用于绘制面板内容的颜色。

    【讨论】:

    • 成功了!有点。我添加了一个打印语句以在每次调用其中一个绘制方法时运行,结果如下: RECT RECT RECT OVAL RECT
    • 为什么最后的矩形会覆盖东西!!?阿格格格
    • 您实际上在 BorderLayout 的 CENTER 中有两个组件。 add(...) 方法不会删除现有组件。因此,在添加新面板之前,您需要先移除原始面板。或者也许更好的设计是改变你的班级的一个属性。因此,您不仅可以在创建面板时定义类型,还可以使用 setType(...) 方法将形状从 Rectangle 更改为 Oval。
    • @camickr 我使用了第二种方法,它成功了!非常感谢!我真的很挣扎。不过,我还有一个简单的问题,你能说出 repaint() 和 revalidate() 之间的区别吗?
    • @Adam,所有组件都是使用默认大小/位置 0 创建的,因此没有什么可绘制的。您使用 revalidate() 来调用布局管理器,以便根据布局管理器的规则为组件指定大小/位置。 repaint() 然后绘制组件。 I used the second method - 那么 revalidate()、repaint() 应该是 setType() 方法的一部分。虽然 revalidate() 仅在您更改要绘制的形状的大小时才真正需要。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-17
    • 1970-01-01
    • 2014-06-03
    • 2011-04-20
    • 1970-01-01
    相关资源
    最近更新 更多