在单独的方法/类中声明时,JLabel和TextFields不会出现

时间:2016-06-04 12:10:49

标签: java swing jpanel jlabel textfield

我在制作JLabel和textFields时遇到了一些麻烦。 如果我将所有这些代码放在main方法中它可以正常工作,但是当我将JLabel和TextFields移动到它们自己的方法或类中时,JPanel仍然是空的。我用的图像显示了。

package gui;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

@SuppressWarnings("serial")
class ImagePanel extends JPanel {

    private Image img;

    public ImagePanel(String img) {
        this(new ImageIcon(img).getImage());
    }

    public ImagePanel(Image img) {
        this.img = img;
        Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
        setPreferredSize(size);
        setMinimumSize(size);
        setMaximumSize(size);
        setSize(size);
        setLayout(null);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(img,  0,  0,  null);
    }
}

public class EquippedInput {

    private JPanel panel;

    public static void main(String[] args){
        ImagePanel panel = new ImagePanel(new ImageIcon("Images/Crusader Background.jpg").getImage());
        JScrollPane scrollBar = new JScrollPane(panel,
                JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        panel.setLayout(null);
        JFrame frame = new JFrame();
        frame.getContentPane().add(scrollBar);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(1160, 1000);
        frame.setVisible(true);
        panel.setPreferredSize(new Dimension(1125, 1210));
        scrollBar.getVerticalScrollBar().setUnitIncrement(20);
    }

    public EquippedInput() {
        initialize();
    }

    private void initialize() {

        /**
         * Stats and slots labels.
         */
        JLabel lblWeaponAttacksPerSecond = new JLabel("Weapon Attacks Per Second");
        JLabel lblWeaponAttackSpeed = new JLabel("Attack Speed");
        JLabel lblMainHand = new JLabel("Main Hand");
        JLabel lblOffHand = new JLabel("Off Hand");

        JLabel stats[] = {lblWeaponAttacksPerSecond, lblWeaponAttackSpeed};
        JLabel slots[] = {lblMainHand, lblOffHand};

        /**
         * Place stats and slots labels.
         */
        for (int i = 0; i < stats.length; i++) {
            stats[i].setBounds(10, (40 + 30 * i), 200, 20);
            panel.add(stats[i]);
        }
        for (int i = 0; i < slots.length; i++) {
            slots[i].setBounds((220 +  70 * i), 10, 60, 20);
            panel.add(slots[i]);
        }

        /**
         * Text fields.
         */
        JTextField textField0 = new JTextField();
        JTextField textField1 = new JTextField();

        JTextField mainHandTextField[] = {textField0, textField1};

        /**
         * Arrays of whether a stat can roll on an item. 1 = can roll. 0 = can't roll.
         */
        int mainHandAvailableStats[] =  {0, 1};

        /**
         * Text field builders, each loop is a single slot.
         */
        for (int i = 0; i < mainHandTextField.length; i++) {
            panel.add(mainHandTextField[i]);
            if(mainHandAvailableStats[i] == 1) {
                int textFieldVerticalPosition = 40 + 30 * i;
                mainHandTextField[i].setBounds(220, textFieldVerticalPosition, 60, 20);
                panel.add(mainHandTextField[i]);
            }
        }
    }
}

实际代码为JPanel提供了更多内容,但这会产生完全相同的结果。

2 个答案:

答案 0 :(得分:2)

我将不得不稍后解释这段代码和这个答案,但它显示:

  1. 从文本文件中获取数据并从中创建表模型
  2. 创建并显示带有空单元格不透明的JTable
  3. 在JPanel中显示背景图片
  4. 数据文件是:

                            Main_Hand       Off_Hand        Head            Shoulder        Neck
    Weapon_Attacks_per_sec  5               null            null            null            null 
    Attack_Speed            20              null            null            null            null
    Damage_%                30              null            null            null            null
    Min_Bonus_Damage        3               null            null            null            null
    Max_Bonus_Damage        40              null            null            null            null
    Min_Weapon_Damage       30              null            null            null            null
    Max_Weapon_Damage       80              null            null            null            null
    Strength                70              50              20              30              30
    

    它必须命名为TableFunData.txt,并且与代码所在的目录/包中相同。

    代码是:

    import java.awt.BorderLayout;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.image.BufferedImage;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    import java.util.Scanner;
    import java.util.Vector;
    
    import javax.imageio.ImageIO;
    import javax.swing.*;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.DefaultTableModel;
    import javax.swing.table.TableModel;
    
    @SuppressWarnings("serial")
    public class TableFun extends JPanel {
        private static final String IMG_PATH = "https://upload.wikimedia.org/"
                + "wikipedia/commons/d/d1/Ozanne-Brest.jpg";
        private JTable table = new JTable();
        private BufferedImage img;
    
        public TableFun(BufferedImage img, TableModel model) {
            this.img = img;
            table = new JTable(model);
            table.setDefaultRenderer(Object.class, new MyCellRenderer());
            table.setOpaque(false);
            table.setPreferredScrollableViewportSize(table.getPreferredSize());
            table.setShowGrid(false);
            JScrollPane scrollPane = new JScrollPane(table);
            scrollPane.setOpaque(false);
            scrollPane.getViewport().setOpaque(false);
    
            setLayout(new BorderLayout());
            add(scrollPane, BorderLayout.CENTER);
        }
    
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            if (img != null) {
                g.drawImage(img, 0, 0, this);
            }
        }
    
        @Override
        public Dimension getPreferredSize() {
            Dimension superSize = super.getPreferredSize();
            if (isPreferredSizeSet() || img == null) {
                return superSize;
            }
            int supW = superSize.width;
            int supH = superSize.height;
            int imgW = img.getWidth();
            int imgH = img.getHeight();
            int w = Math.max(imgW, supW);
            int h = Math.max(imgH, supH);
            return new Dimension(w, h);
        }
    
        private class MyCellRenderer extends DefaultTableCellRenderer {
            @Override
            public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus,
                    int row, int column) {
                DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
                if (column != 0) {
                    renderer.setHorizontalAlignment(JLabel.CENTER);
                } else {
                    renderer.setHorizontalAlignment(JLabel.LEADING);
                }
                renderer.setOpaque(value != null);
                return renderer;
            }
        }
    
        private static void createAndShowGui() {
            BufferedImage img = null;
            try {
                URL imageUrl = new URL(IMG_PATH);
                img = ImageIO.read(imageUrl);
            } catch (IOException e1) {
                e1.printStackTrace();
                System.exit(-1);
            }
            String dataPath = "TableFunData.txt";
            DataIO dataIO = new DataIO(dataPath);
            TableModel model = null;
            try {
                model = dataIO.createTableModel();
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(-1);
            }
    
            JFrame frame = new JFrame("Table Fun");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.getContentPane().add(new TableFun(img, model));
            frame.pack();
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);
        }
    
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> createAndShowGui());
        }
    }
    
    class DataIO {
    
        private static final String NULL = "null";
        private String dataPath;
    
        public DataIO(String dataPath) {
            this.dataPath = dataPath;
        }
    
        public TableModel createTableModel() throws IOException {
            InputStream inputStream = getClass().getResourceAsStream(dataPath);
            Scanner scanner = new Scanner(inputStream);
            Vector<String> columnNames = new Vector<>();
            Vector<Vector<Object>> data = new Vector<>();
    
            while (scanner.hasNext()) {
                String line = scanner.nextLine();
                if (columnNames.size() == 0) {
                    columnNames = createColumnNames(line);
                } else {
                    Vector<Object> dataRow = createDataRow(line);
                    data.add(dataRow);
                }
            }
            if (scanner != null) {
                scanner.close();
            }
            DefaultTableModel model = new DefaultTableModel(data, columnNames);
            return model;
        }
    
        private Vector<String> createColumnNames(String line) {
            String[] tokens = line.split("\\s+");
            Vector<String> columnNames = new Vector<>();
            columnNames.add(" "); // first name is blank
            for (String token : tokens) {
                if (!token.trim().isEmpty()) {
                    token = token.replace("_", " "); // add spaces
                    columnNames.add(token);
                }
            }
            return columnNames;
        }
    
        private Vector<Object> createDataRow(String line) {
            String[] tokens = line.split("\\s+");
            Vector<Object> dataRow = new Vector<>();
            for (String token : tokens) {
                token = token.trim();
                if (!token.isEmpty()) {
                    // first token is the title
                    if (dataRow.size() == 0) {
                        token = token.replace("_", " "); // add spaces
                        dataRow.add(token);
                    } else {
                        // if title already added
                        if (token.equalsIgnoreCase(NULL)) {
                            dataRow.add(null);
                        } else {
                            int value = Integer.parseInt(token);
                            dataRow.add(value);
                        }
                    }
                }
            }
            return dataRow;
        }
    
    }
    

    GUI看起来像:

    enter image description here

    现在有一些解释:

    好的,这段代码的作用是什么:

    首先,我使用外部图像,可以从维基百科/维基媒体免费获得,以便我的代码可以从任何计算机运行,并演示在JPanel中使用图像。图像路径可以在这里找到:

    private static final String IMG_PATH = "https://upload.wikimedia.org/"
            + "wikipedia/commons/d/d1/Ozanne-Brest.jpg";
    

    并且它在这里用于创建图像:

            URL imageUrl = new URL(IMG_PATH);
            img = ImageIO.read(imageUrl);
    

    然后在JPanel的paintComponent方法中绘制:

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (img != null) {
            g.drawImage(img, 0, 0, this);
        }
    }
    

    我的代码还扩展了JPanel,因为这为我的GUI程序提供了比他们扩展JFrame时更大的灵活性:

    public class TableFun extends JPanel {
    

    我覆盖了JPanel的getPreferredSize方法,使其大小适合图片,除非需要更大。这就是为什么我首先获得超级首选尺寸,并尝试使我的GUI足够大以显示图像,如果需要显示更多组件则更大:

    @Override
    public Dimension getPreferredSize() {
        Dimension superSize = super.getPreferredSize();
        if (isPreferredSizeSet() || img == null) {
            return superSize;
        }
        int supW = superSize.width;
        int supH = superSize.height;
        int imgW = img.getWidth();
        int imgH = img.getHeight();
        int w = Math.max(imgW, supW);
        int h = Math.max(imgH, supH);
        return new Dimension(w, h);
    }
    

    为了简化代码,我尝试将代码与数据分开,并将我的数据放在文本文件中。 DataIO类是一个小实用程序类,用于读取文件所持有的文本,然后逐行解析数据以创建和填充DefaultTableModel对象。请注意,我得到的文件不是&#34;文件&#34;而是作为一个类资源,因为这样我可以将它包含在jar文件中,如果我想这样做的话。我使用扫描仪读取每一行,就像你为文本文件所做的那样。

    public TableModel createTableModel() throws IOException {
        InputStream inputStream = getClass().getResourceAsStream(dataPath);
        Scanner scanner = new Scanner(inputStream);
    

    一旦我得到一行文字,我就用白色空格分割它,这会创建一个字符串数组,并修剪掉所有空格:

    String[] tokens = line.split("\\s+");
    

    JTable使用名为MyCellRenderer的表格单元格渲染器

    table.setDefaultRenderer(Object.class, new MyCellRenderer());
    

    如果单元格保存数据,则使单元格不透明;如果单元格保持空值,则使其不透明(清除):

    renderer.setOpaque(value != null);
    

    我还确保JTable本身,JScrollPane和scrollpane的视口都是非透明的,这样图像就可以显示出来:

        table.setOpaque(false);
    
        // ....
    
        scrollPane.setOpaque(false);
        scrollPane.getViewport().setOpaque(false);
    

    你提到了一个被抛出的NPE,这可能意味着你的Java程序没有找到文本文件。同样,它必须与您的类文件一起放置。您应该在与java文件相同的目录中创建一个Eclipse 的文本文件,将其精确命名为 TableFunData.txt (拼写和大小写),以及何时#&重新完成,Eclipse应该看起来像:

    enter image description here

    使用Eclipse的软件包资源管理器(以蓝色和红色突出显示)在同一个软件包中看到代码和数据文本,代码的软件包语句应该显示它实际上在这里包装(绿色)。

答案 1 :(得分:0)

这是一个简单的JTable实现,正如@Hovercraft Full Of Eels所建议的那样。 基于数据呈现背景颜色。 1将导致背景颜色为蓝色,而0将呈现为红色。 (该演示基于https://docs.oracle.com/javase/tutorial/displayCode.html?code=https://docs.oracle.com/javase/tutorial/uiswing/examples/components/SimpleTableDemoProject/src/components/SimpleTableDemo.java

public class TableDemo extends JPanel {

    public TableDemo() {
        super(new GridLayout(1,0));

        String[] columnNames = {"         ",
                "Main Hand",
                "Off Hand",
                "Head",
                "Shoulder",
        "Neck"};

        Object[][] data = {
                {"Weapon Attacks Per Second", new Integer(1), new Integer(0), new Integer(0),new Integer(0),new Integer(0)},
                {"Attack Speed", new Integer(1), new Integer(0), new Integer(1),new Integer(0),new Integer(0)},
                {"Damage%", new Integer(1), new Integer(0), new Integer(0),new Integer(0),new Integer(0)},
                {"Min Bonus Damage", new Integer(1), new Integer(0), new Integer(0),new Integer(1),new Integer(0)},
                {"Max Bonus Damage", new Integer(1), new Integer(1), new Integer(0),new Integer(0),new Integer(0)},
                {"Min Weapon Damage", new Integer(1), new Integer(0), new Integer(0),new Integer(1),new Integer(0)},
                {"Max Weapon Damage", new Integer(1), new Integer(0), new Integer(1),new Integer(0),new Integer(0)},
        };

        final JTable table = new JTable(data, columnNames);
        table.setPreferredScrollableViewportSize(new Dimension(600, 70));


        table.getColumnModel().getColumn(1).setCellRenderer(new ColorRenderer());
        table.getColumnModel().getColumn(2).setCellRenderer(new ColorRenderer());
        table.getColumnModel().getColumn(3).setCellRenderer(new ColorRenderer());
        table.getColumnModel().getColumn(4).setCellRenderer(new ColorRenderer());
        table.getColumnModel().getColumn(5).setCellRenderer(new ColorRenderer());

        //Create the scroll pane and add the table to it.
        JScrollPane scrollPane = new JScrollPane(table);

        //Add the scroll pane to this panel.
        add(scrollPane);
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event-dispatching thread.
     */
    private static void createAndShowGUI() {
        //Create and set up the window.
        JFrame frame = new JFrame("TableDemo");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create and set up the content pane.
        TableDemo newContentPane = new TableDemo();
        newContentPane.setOpaque(true); //content panes must be opaque
        frame.setContentPane(newContentPane);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event-dispatching thread:
        //creating and showing this application's GUI.
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

class ColorRenderer extends DefaultTableCellRenderer {

    public ColorRenderer() {

        setOpaque(true); //MUST do this for background to show up.
    }

    @Override
    public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected,
            boolean hasFocus,int row, int column) {
        if((int)value == 1) {
            setBackground(Color.BLUE);
        }else {
            setBackground(Color.RED);
        }

        return this;
    }
}

enter image description here