0

我修改了我的paint的for循环方法,该方法将JPanels方块绘制到与新添加的JPanels有关的所有内容都不像以前那样在for循环中,而是在它自己的称为addBlock(..)的方法中。在我这样做之后,JPanels 不再出现。

基本上我试图用这个程序做的是能够按需添加和删除 JPanel(由 60x60 块表示)。这就是我使用 ArrayList 的原因......所以我所要做的就是在之后调用 paint() 方法,它会根据我的 ArrayList 中有多少元素重新绘制。这是早期阶段,我还是新手,所以我什至不确定是否有更有效的方法。现在我只想展示一些东西。

这是我的代码:

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

class TestApp extends JFrame{
    JFrame frame = new JFrame();
    ArrayList<JPanel> grid = new ArrayList<JPanel>();

    private static int amount = 10;

    private void paint()
    {   
        for(int i = 0, x = 0, y = 0; i < amount; i++, x += 62)
        {
            addBlock(i, x, y);
        }
    }

    //Adds a block
    private void addBlock(int index, int x, int y){
        int height = 60;
        int width = 60;

        grid.add(new JPanel());
        frame.add(grid.get(index));

        (grid.get(index)).setVisible(true);
        (grid.get(index)).setBounds(x, y, width, height);
    }  

    //Removes a block
    private void removeFrame(int index){
        frame.remove(grid.get(index));
        grid.remove(index);
    }  

    //Default Constructor (sets up JFrame)
    TestApp(){ 
        frame.setLayout(null);
        frame.setPreferredSize(new Dimension(600, 300));
        frame.setTitle("Test Program");
        frame.setBackground(Color.WHITE); 
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setAlwaysOnTop(rootPaneCheckingEnabled);
        frame.setResizable(true);
        frame.setVisible(true);
    }

    public static void main(String [] args) {
        TestApp program = new TestApp();
        program.paint();
    }
}

有什么想法或建议吗?

编辑:这是固定和改进的代码。我还没有实施其他建议的事情,因为我还没有做足够的研究。

package my;

import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
import javax.swing.border.LineBorder;

class TestApp extends JFrame{
    JFrame frame = new JFrame();
    ArrayList<JButton> grid = new ArrayList<JButton>();

    private static int amount = 46;
    private static int counter = 0;

    private void paintGrid()
    {   
        for(int i = 0, y = 4; i < ((amount / 10) + (amount % 10)); i++, y += 104)
        {
            for(int j = 0, x = 4; j < 10 && (counter < amount); j++, x += 84)
            {
                addBlock(counter, x, y);
                counter++;
            }
        }
    }

    //Adds a block
    private void addBlock(int index, int x, int y){
        int height = 100;
        int width = 80;

        grid.add(new JButton());
        (grid.get(index)).setBackground(Color.YELLOW);
        (grid.get(index)).setBorder(new LineBorder(Color.BLACK));
        (grid.get(index)).setVisible(true);
        (grid.get(index)).setBounds(x, y, width, height);

        frame.add(grid.get(index));
    }  

    //Removes a block
    private void removeBlock(int index){
        frame.remove(grid.get(index));
        grid.remove(index);
    }  

    //Default Constructor (sets up JFrame)
    TestApp(){ 
        frame.setLayout(null);
        frame.setPreferredSize(new Dimension(850, 600));
        frame.setTitle("Test Program");        
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.setAlwaysOnTop(rootPaneCheckingEnabled);
        frame.setResizable(false);
        frame.setVisible(true);
    }

    public static void main(String [] args) {
        TestApp program = new TestApp();
        program.paintGrid();
    }
}
4

4 回答 4

2

为了在组件上进行自定义绘制,您需要创建一个如下所示的方法:

public void paintComponent(Graphics g)

这是Swing 调用来绘制组件的唯一方法。

话虽如此,该paintComponent()方法旨在使用类的方法在现有UI 组件上绘制某些内容Graphics。您不应该创建新组件来添加到当前 UI。

我建议您创建一个 JPanel 的子类,它为您的网格中的单个元素进行自定义绘制。然后将任意数量的这些自定义 JPanel 添加到 JFrame。

于 2013-05-09T05:53:07.017 回答
2

问题是,你怎么知道没有添加面板?它们与父面板的颜色相同吗?

尝试更改addBlock方法以突出显示每个面板...

private void addBlock(int index, int x, int y){
    int height = 60;
    int width = 60;

    JPanel panel = new JPanel()
    panel.setBorder(new LineBorder(Color.BLACK));
    grid.add(panel);
    frame.add(grid.get(index));

    (grid.get(index)).setVisible(true);
    (grid.get(index)).setBounds(x, y, width, height);
}  

一个忠告,虽然null布局看起来很有吸引力,但它们最终会花费你更多的时间和精力,然后一个或多个布局管理器的深思熟虑的应用程序将......

ps - 我也会避免使用被调用的方法paint,因为它们会让其他人感到困惑。

于 2013-05-09T05:54:59.097 回答
2
  1. 永远不要在 paint() / paintComponent() 方法中添加 JComponents

  2. paint() / paintComponent() 在所有鼠标和键事件之后被调用,内部来自 API 中实现的方法

  3. continer 不知道在运行时添加了任何 JComponent,必须调用 revalidate() & repaint()

  4. 请阅读Oracle 教程 2D 图形

  5. (空或包含图形)JPanel 默认从不返回任何大小

于 2013-05-09T05:59:32.677 回答
1
  1. 您没有指定任何LayoutManager. Swing 布局管理器为您提供最适合您的概览,并替换frame.setLayout(null);Null 布局不是一个好的选择!

  2. 你添加 JPanels。即使它有效,你也不会看到任何东西。我修改了应用程序,它适用于FlowLayoutand JLabels

    import java.awt.*;
    import java.util.ArrayList;
    import javax.swing.*;
    
    public class TestApp extends JFrame{
        JFrame frame = new JFrame();
        ArrayList<JLabel> grid = new ArrayList<JLabel>();
    
        private static int amount = 10;
    
        private void paint()
        {   
            for(int i = 0, x = 0, y = 0; i < amount; i++, x += 62)
            {
                addBlock(i, x, y);
            }
        }
    
        //Adds a block
        private void addBlock(int index, int x, int y){
            int height = 60;
            int width = 60;
    
            grid.add(new JLabel("hello"));
            frame.add(grid.get(index));
    
            (grid.get(index)).setVisible(true);
            (grid.get(index)).setBounds(x, y, width, height);
    
            frame.revalidate();
            frame.repaint();
        }  
    
        //Removes a block
        private void removeFrame(int index){
            frame.remove(grid.get(index));
            grid.remove(index);
        }  
    
        //Default Constructor (sets up JFrame)
        TestApp(){ 
            frame.setLayout(new FlowLayout());
            frame.setPreferredSize(new Dimension(600, 300));
            frame.setTitle("Test Program");
            frame.setBackground(Color.WHITE); 
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
            frame.setAlwaysOnTop(rootPaneCheckingEnabled);
            frame.setResizable(true);
            frame.setVisible(true);
        }
    
        public static void main(String [] args) {
            TestApp program = new TestApp();
            program.paint();
    }
    }
    
于 2013-05-09T06:03:29.493 回答